Meilleure façon de mélanger deux listes connexes
Existe-t-il de meilleurs moyens de mélanger aléatoirement deux listes associées sans casser leur correspondance dans l'autre liste? J'ai trouvé des questions connexes dans numpy.array
et c#
mais pas exactement la même.
Comme premier essai, un simple truc zip
fera l'affaire:
import random
a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
b = [2, 4, 6, 8, 10]
c = zip(a, b)
random.shuffle(c)
a = [e[0] for e in c]
b = [e[1] for e in c]
print a
print b
Il obtiendra la sortie:
[[1, 2], [7, 8], [3, 4], [5, 6], [9, 10]]
[2, 8, 4, 6, 10]
Trouve ça un peu gênant. Et il a également besoin d'une liste supplémentaire.
6 réponses
Compte tenu de la relation démontrée dans la question, je vais supposer que les listes ont la même longueur et que list1[i]
correspond à list2[i]
pour tout index i
. Avec cette hypothèse en place, mélanger les listes est aussi simple que mélanger les indices:
from random import shuffle
# Given list1 and list2
list1_shuf = []
list2_shuf = []
index_shuf = range(len(list1))
shuffle(index_shuf)
for i in index_shuf:
list1_shuf.append(list1[i])
list2_shuf.append(list2[i])
Si vous souhaitez installer quelques paquets supplémentaires:
Req: NumPy (>=1.6.1), SciPy (>=0,9).
Pip install-U scikit-learn
from sklearn.utils import shuffle
list_1, list_2 = shuffle(list_1, list_2)
Si vous avez à le faire souvent, vous pourriez envisager d'ajouter un niveau d'indirection en mélangeant une liste d'index.
Python 2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import random
>>> a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
>>> b = [2, 4, 6, 8, 10]
>>> indexes = range(len(a))
>>> indexes
[0, 1, 2, 3, 4]
>>> random.shuffle(indexes)
>>> indexes
[4, 1, 2, 0, 3]
>>> for index in indexes:
... print a[index], b[index]
...
[9, 10] 10
[3, 4] 4
[5, 6] 6
[1, 2] 2
[7, 8] 8
Une réponse rapide en utilisant numpy veuillez vous référer à ici :
Vous pouvez utiliser
p = numpy.random.permutation(len(a))
Pour créer une nouvelle liste d'index pour les deux listes et l'utiliser pour les réorganiser.
Dans votre scénario:
In [61]: a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
In [62]: b = [2, 4, 6, 8, 10]
In [63]: import numpy as np
In [64]: a_ar, b_ar = np.array(a), np.array(b)
In [65]: p = np.random.permutation(len(a))
In [66]: a, b = a_ar[p].tolist(), b_ar[p].tolist()
In [68]: a
Out[68]: [[3, 4], [7, 8], [5, 6], [1, 2], [9, 10]]
In [69]: b
Out[69]: [4, 8, 6, 2, 10]
Jusqu'à présent, toutes les solutions ont créé de nouvelles listes afin de résoudre le problème. Si la liste un et b sont très long, vous pouvez les mélanger à la place. Pour cela, vous auriez besoin d'une fonction comme:
import random
def shuffle(a,b):
assert len(a) == len(b)
start_state = random.getstate()
random.shuffle(a)
random.setstate(start_state)
random.shuffle(b)
a = [1,2,3,4,5,6,7,8,9]
b = [10,11,12,13,14,15,16,17,18,19]
shuffle(a,b)
print(a) # [9, 7, 3, 1, 2, 5, 4, 8, 6]
print(b) # [19, 17, 13, 11, 12, 15, 14, 18, 16]
Je ne suis pas sûr de manquer quelque chose ici, mais il semble que vous ne fassiez que mélanger 1 des listes et que l'autre soit réorganisée pour correspondre à l'ordre de la première liste. Donc, ce que vous avez est la meilleure façon de le faire sans le rendre plus compliqué. Si vous voulez suivre la route compliquée, vous pouvez simplement mélanger la liste 1 et utiliser la liste non brouillée pour faire une recherche dans la liste mélangée et la réorganiser de cette façon. En fin de compte, vous vous retrouvez avec le même résultat que vous avez commencé avec. Pourquoi la création d'un troisième liste un problème? Si vous voulez vraiment recycler les listes, vous pouvez simplement remplacer la liste b par ce que vous utilisez pour la liste c, puis la séparer plus tard en a et B.