910 votes

Mélange d'une liste d'objets

J'ai une liste d'objets et je veux les mélanger. Je pensais pouvoir utiliser la fonction random.shuffle mais cela semble échouer lorsque la liste est constituée d'objets. Existe-t-il une méthode pour mélanger les objets ou un autre moyen de contourner ce problème ?

import random

class A:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1, a2]

print(random.shuffle(b))

Cela va échouer.

7 votes

Pouvez-vous donner un exemple d'échec ? random.shuffle devrait fonctionner de manière invariante par rapport au type des objets de la liste.

4 votes

>>> a1 = a() >>> a2 = a() >>> b = [a1,a2] >>> b [<__main__.a instance at 0xb7df9e6c>, <__main__.a instance at 0xb7df9e2c>] >>> print random.shuffle(b) None

154 votes

Comme indiqué ci-dessous, random.shuffle ne renvoie pas une nouvelle liste mélangée ; il mélange la liste en place. Vous ne devriez donc pas dire "print random.shuffle(b)" mais plutôt effectuer le mélange sur une ligne et imprimer b sur la ligne suivante.

1433voto

tom10 Points 19886

random.shuffle devrait fonctionner. Voici un exemple, où les objets sont des listes :

from random import shuffle
x = [[i] for i in range(10)]
shuffle(x)

# print(x)  gives  [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]
# of course your results will vary

Notez que le shuffle fonctionne en place et renvoie None.

0 votes

Est-ce qu'il y a quelques graines aléatoires ou est-ce que c'est vraiment aléatoire (avec peut-être un élément temporel) ?

1 votes

@seokhoonlee Ni l'un ni l'autre. Il s'agit d'un générateur de nombres pséduo-aléatoires qui, lorsque cela est possible, est ensemencé par une source de caractère aléatoire réel provenant du système d'exploitation. Pour tout sauf pour la cryptographie, il est "suffisamment" aléatoire. Ceci est expliqué en détail dans le random documentation du module .

2 votes

utiliser le clone pour une nouvelle liste

133voto

Ted Points 139

Comme vous l'avez appris, c'est le brassage sur place qui pose problème. J'ai aussi souvent ce problème, et je semble souvent oublier comment copier une liste, aussi. En utilisant sample(a, len(a)) est la solution, en utilisant len(a) comme la taille de l'échantillon. Voir https://docs.python.org/3.6/library/random.html#random.sample pour la documentation Python.

Voici une version simple utilisant random.sample() qui retourne le résultat mélangé comme une nouvelle liste.

import random

a = range(5)
b = random.sample(a, len(a))
print a, b, "two list same:", a == b
# print: [0, 1, 2, 3, 4] [2, 1, 3, 4, 0] two list same: False

# The function sample allows no duplicates.
# Result can be smaller but not larger than the input.
a = range(555)
b = random.sample(a, len(a))
print "no duplicates:", a == list(set(b))

try:
    random.sample(a, len(a) + 1)
except ValueError as e:
    print "Nope!", e

# print: no duplicates: True
# print: Nope! sample larger than population

2 votes

Existe-t-il une option qui ne modifie pas le tableau original mais renvoie un nouveau tableau mélangé ?

0 votes

Copiez juste la liste @CharlieParker : old = [1,2,3,4,5]; new = list(old); random.shuffle(new); print(old); print(new) (remplacer ; par des nouvelles lignes)

0 votes

old[:] on pourrait aussi faire une copie superficielle pour la liste old .

49voto

Michael Points 81
#!/usr/bin/python3

import random

s=list(range(5))
random.shuffle(s) # << shuffle before print or assignment
print(s)

# print: [2, 4, 1, 3, 0]

25voto

Dan Lorenc Points 4180
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

Cela fonctionne bien pour moi. Assurez-vous de définir la méthode aléatoire.

0 votes

Cela ne fonctionne toujours pas pour moi, voir mon exemple de code dans la question éditée.

5 votes

Le deuxième paramètre est random.random par défaut. Il est tout à fait possible de ne pas le prendre en compte.

3 votes

@alvas random.shuffle(a) ne renvoie rien, c'est-à-dire qu'il renvoie None . Vous devez donc vérifier une valeur non retournée.

7voto

JonDoe Points 11

print func(foo)' imprimera la valeur de retour de 'func' lorsqu'il est appelé avec 'foo'. Cependant, le type de retour de 'shuffle' est None, car la liste sera modifiée sur place, et il n'imprime donc rien. Solution :

# shuffle the list in place 
random.shuffle(b)

# print it
print(b)

Si vous êtes plus proche du style de programmation fonctionnelle, vous pouvez créer la fonction d'encapsulation suivante :

def myshuffle(ls):
    random.shuffle(ls)
    return ls

2 votes

Comme cela passe une référence à la liste, l'original est modifié. Vous pourriez vouloir copier la liste avant de la mélanger en utilisant copie profonde

0 votes

@shivram.ss Dans ce cas, vous voudriez quelque chose comme random.sample(ls, len(ls)) si vous voulez vraiment emprunter cette voie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X