web-dev-qa-db-fra.com

Mélanger une liste d'objets

J'ai une liste d'objets dans Python et je veux les mélanger. Je pensais pouvoir utiliser la méthode 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 une autre manière de contourner cela?

import random

class a:
    foo = "bar"

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

print random.shuffle(b)

Cela va échouer.

693
utdiscant

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 shuffle fonctionne à la place et renvoie Aucun.

1140
tom10

Comme vous l'avez appris, le problème était le brassage sur place. J'ai aussi souvent des problèmes et semble souvent oublier comment copier une liste. Utiliser sample(a, len(a)) est la solution, en utilisant len(a) comme taille d’é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 renvoie le résultat mélangé sous la forme d'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
104
Ted

Cela m'a pris du temps pour l'obtenir aussi. Mais la documentation pour shuffle est très claire:

liste aléatoire x en place; retourner Aucun.

Donc, vous ne devriez pas print random.shuffle(b). À la place, faites random.shuffle(b) puis print b.

48
Ohad Cohen
#!/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]
35
Michael

Si vous utilisez déjà numpy (très populaire pour les applications scientifiques et financières), vous pouvez économiser une importation.

import numpy as np    
np.random.shuffle(b)
print(b)

http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.shuffle.html

26
fantabolous
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

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

22
Dan Lorenc

Si vous avez plusieurs listes, vous pouvez commencer par définir la permutation (la façon dont vous mélangez/réorganisez les éléments de la liste) puis appliquez-la à toutes les listes:

_import random

perm = list(range(len(list_one)))
random.shuffle(perm)
list_one = [list_one[index] for index in perm]
list_two = [list_two[index] for index in perm]
_

Numpy/Scipy

Si vos listes sont des tableaux numpy, c'est plus simple:

_import numpy as np

perm = np.random.permutation(len(list_one))
list_one = list_one[perm]
list_two = list_two[perm]
_

mpu

J'ai créé le petit paquet utilitaire mpu qui a la fonction consistent_shuffle :

_import mpu

# Necessary if you want consistent results
import random
random.seed(8)

# Define example lists
list_one = [1,2,3]
list_two = ['a', 'b', 'c']

# Call the function
list_one, list_two = mpu.consistent_shuffle(list_one, list_two)
_

Notez que _mpu.consistent_shuffle_ prend un nombre arbitraire d'arguments. Ainsi, vous pouvez également mélanger trois listes ou plus avec elle.

11
Martin Thoma
from random import random
my_list = range(10)
shuffled_list = sorted(my_list, key=lambda x: random())

Cette alternative peut être utile pour certaines applications où vous souhaitez échanger la fonction de commande.

8
Jeff

Dans certains cas, lors de l'utilisation de tableaux numpy, l'utilisation de random.shuffle créait des données en double dans le tableau.

Une alternative consiste à utiliser numpy.random.shuffle. Si vous travaillez déjà avec numpy, cette méthode est préférable au générique random.shuffle.

numpy.random.shuffle

Exemple

>>> import numpy as np
>>> import random

Utiliser random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [1, 2, 3],
       [4, 5, 6]])

Utiliser numpy.random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> np.random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [7, 8, 9],
       [4, 5, 6]])
6
Gordon Bean

'print func (foo)' affichera la valeur de retour de 'func' lorsqu'il sera appelé avec 'foo'. 'shuffle' a toutefois la valeur None comme type de retour, car la liste sera modifiée à la place, elle n'imprimera donc rien. Solution de contournement:

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

# print it
print(b)

Si vous êtes plus dans le style de programmation fonctionnelle, vous voudrez peut-être créer la fonction wrapper suivante:

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

On peut définir une fonction appelée shuffled (dans le même sens que sort vs sorted)

def shuffled(x):
    import random
    y = x[:]
    random.shuffle(y)
    return y

x = shuffled([1, 2, 3, 4])
print x
3
malbarbo

Pour les one-liners, utilisezrandom.sample(list_to_be_shuffled, length_of_the_list) avec un exemple:

import random
random.sample(list(range(10)), 10)

sorties: [2, 9, 7, 8, 3, 0, 4, 1, 6, 5]

3
weiyixie
import random

class a:
    foo = "bar"

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

random.shuffle(b)
print(b)

shuffle est en place, donc n'imprimez pas le résultat, qui est None, mais la liste.

2
ravi tanwar

vous pouvez créer une fonction qui prend une liste en tant que paramètre et renvoie une version aléatoire de la liste:

from random import *

def listshuffler(inputlist):
    for i in range(len(inputlist)):
        swap = randint(0,len(inputlist)-1)
        temp = inputlist[swap]
        inputlist[swap] = inputlist[i]
        inputlist[i] = temp
    return inputlist
0
user8327014
def shuffle(_list):
    if not _list == []:
        import random
        list2 = []
        while _list != []:
            card = random.choice(_list)
            _list.remove(card)
            list2.append(card)
        while list2 != []:
            card1 = list2[0]
            list2.remove(card1)
            _list.append(card1)
        return _list
0
Pogramist

Vous pouvez y aller pour ça:

>>> A = ['r','a','n','d','o','m']
>>> B = [1,2,3,4,5,6]
>>> import random
>>> random.sample(A+B, len(A+B))
[3, 'r', 4, 'n', 6, 5, 'm', 2, 1, 'a', 'o', 'd']

si vous souhaitez revenir à deux listes, vous divisez cette longue liste en deux.

0
kiriloff

Assurez-vous de ne pas nommer votre fichier source random.py et qu'il n'y a pas de fichier dans votre répertoire de travail appelé random.pyc. .

0
user3298224
""" to shuffle random, set random= True """

def shuffle(x,random=False):
     shuffled = []
     ma = x
     if random == True:
         rando = [ma[i] for i in np.random.randint(0,len(ma),len(ma))]
         return rando
     if random == False:
          for i in range(len(ma)):
          ave = len(ma)//3
          if i < ave:
             shuffled.append(ma[i+ave])
          else:
             shuffled.append(ma[i-ave])    
     return shuffled
0
Josh Anish
import random
class a:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1.foo,a2.foo]
random.shuffle(b)
0
Xavier

vous pouvez utiliser shuffle ou sample. qui viennent tous deux du module aléatoire.

import random
def shuffle(arr1):
    n=len(arr1)
    b=random.sample(arr1,n)
    return b

OR

import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1
0
ravi tanwar