1
votes

Générer des listes remplies de valeurs entières uniques en Python

Tout d'abord, j'aimerais dire que je pensais avoir répondu à la même question auparavant, mais après une brève recherche, je n'ai trouvé aucun fil de discussion m'amenant à la réponse que je voulais ici, ce qui signifie que je n'a pas creusé suffisamment ou a manqué certains mots clés. Désolé pour cela si cette question est là-bas.

Quoi qu'il en soit, j'ai commencé à apprendre le python et je faisais quelques exercices. J'avais besoin de créer une liste contenant 10 entiers générés aléatoirement et chaque entier doit avoir une valeur différente.

J'ai donc essayé de comparer le premier élément de la liste avec le suivant et s'ils sont les mêmes, j'ai essayé de générer un nouveau nombre avec l'instruction if.

import random

listA = []

for i in range(0,10):
    x=random.randint(1,100)

    if listA[i] == listA[i-1]:
        x=random.randint(1,100)
    else:
        listA.append(x)

listA.sort()
print(listA)

Mais j'ai une erreur disant; "list index is out of range"

Je m'attendais à ce que l'instruction if commence par l'index "0" et compte jusqu'au 9ème index de "listA" et au fur et à mesure, comparez-les, si la même chose , générez un autre nombre aléatoire. Mais évidemment, mon indexation était erronée.

De plus, tout autre commentaire sur le code serait apprécié.

Merci pour votre temps à l'avance.


4 commentaires

Vous faites cela if listA [i] == listA [i-1] lorsque la liste est vide


Essayez d'utiliser if x in listA: et vous pouvez utiliser random.sample (range (1, 100), 10) pour créer une liste unique


Vous voulez vérifier l'élément précédent sauf pour la première itération, donc if i> 0 et listA [i] == listA [i-1] résoudront votre problème.


Merci. Cela a été utile. Comme je l'ai dit, puisque je suis vraiment nouveau dans la syntaxe python et que j'apprends avec des exercices, je ne savais pas vraiment que c'était possible. De plus, random.sample est totalement nouveau pour moi.


3 Réponses :


3
votes

Essayez ce qui suit.

import random

listA = []

while(len(listA) < 10):
    x = random.randint(1,100)
    if x not in listA:
        listA.append(x)

listA.sort()
print(listA)

Explication:

Vous devriez utiliser une boucle while pour continuer à générer des nombres jusqu'à ce que votre liste désirée soit en fait de 10 nombres. Lorsque vous utilisez la boucle for, si vous générez [2, 2, 30, 40, 2, 10, 20, 83, 92, 29] au hasard, votre liste ne comportera que 8 nombres car les 2 en double ne seront pas ajouté, bien que vous ayez déjà parcouru votre boucle for 10 fois.

Bien que soit la clé ici, vous ne serez jamais en mesure de prédire à toute épreuve le nombre de fois que cela prendra ont au hasard 10 nombres différents. Par conséquent, vous voulez continuer tant que vous n’avez pas atteint la longueur souhaitée.

De plus, le mot-clé dans est un moyen simple de vérifier si quelque chose existe déjà dans quelque chose d'autre.


8 commentaires

Bonne réponse. Je recommande également random.sample comme meilleure alternative à la boucle while .


Merci, cela a fonctionné et votre explication était compréhensible.


@jpp pourquoi ne pas fournir une réponse séparée qui utilise random.sample ?


@Risadinha, Parce que c'est techniquement une autre question: Comment puis-je créer une liste de nombres aléatoires sans doublons? . Il est généralement bon de répondre pour indiquer des alternatives évidentes et efficaces, même si cela va techniquement au-delà de la question initiale.


J'ai ajouté un exemple utilisant l'échantillonnage sans remplacement - cela me semble être une manière plus logique d'attaquer le problème, mais je conviens que cette réponse est plus proche de la question initiale.


@jpp Je me sens trop stupide pour saisir la "différence technique" ici. Maintenant que vous avez soulevé l'autre question, je pense qu'elle fournit une réponse pratique à celle-ci? Ne sont-ils pas des doublons dans le but de "créer une liste d'entiers aléatoires uniques"?


@Risadinha, Le problème principal , à mon avis, est que la logique de l'OP est techniquement incorrecte. L ' autre question, comment obtenir le même résultat plus efficacement, est également une préoccupation valable, mais n'explique pas le malentendu d'OP.


Ajout des horaires pour toutes les suggestions de stackoverflow.com/a/54535557/5447172



3
votes

En Python, un ensemble ne peut contenir que des valeurs uniques, donc dans le code suivant, les nombres aléatoires en double n'augmenteront pas la longueur de l'ensemble:

[18, 20, 26, 48, 51, 72, 75, 92, 94, 99]

Sortie:

import random

s = set()
while len(s) < 10:
    s.add(random.randint(1,100))

print(sorted(s))


0 commentaires

3
votes

Cela peut être considéré comme un échantillonnage sans remplacement . Dans ce cas, vous "échantillonnez" 10 éléments au hasard de la plage (1, 101) et chaque élément qui est échantillonné ne peut être échantillonné qu'une seule fois (c'est-à-dire qu'il n'est pas "remplacé" - imaginez un dessin numéroté balles au hasard à partir d'un sac pour comprendre le concept).

L'échantillonnage sans remplacement peut être traité en une seule ligne:

def random_sample():
    import random
    return sorted(random.sample(range(1, 101), 10))

def random_shuffle():
    import random
    listA = list(range(1, 101))
    random.shuffle(listA)
    return sorted(listA[:10])

def while_loop():
    import random
    listA = []
    while(len(listA) < 10):
        x = random.randint(1, 100)
        if x not in listA:
            listA.append(x)
    return sorted(listA)

def random_set():
    import random
    s = set()
    while len(s) < 10:
        s.add(random.randint(1, 100))
    return sorted(s)

%timeit for i in range(100): random_sample()
# 1.38 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit for i in range(100): random_shuffle()
# 6.81 ms ± 104 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit for i in range(100): while_loop()
# 1.61 ms ± 18.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit for i in range(100): set_approach()
# 1.48 ms ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Une autre façon de penser est de mélanger list (range (1, 101)) et prenez les 10 premiers éléments:

import random
listA = list(range(1, 101))
random.shuffle(listA)
listA[:10]

Chronométrage des différentes approches p>

Utilisation de la magie % timeit dans iPython a > nous pouvons comparer les différentes approches suggérées dans les réponses:

import random
listA = random.sample(range(1, 101), 10)


2 commentaires

NB - l'équivalent de random.randint (1,100) utilisant une plage nécessiterait range (1,101)


Notez que le random.sample intégré "est particulièrement rapide et peu encombrant pour l'échantillonnage à partir d'une grande population" docs.python.org/3.7/library/random.html#random.sample