web-dev-qa-db-fra.com

Meilleure façon de mélanger deux listes associées

Existe-t-il de meilleurs moyens de mélanger au hasard deux listes liées sans casser leur correspondance dans l'autre liste? J'ai trouvé des questions connexes dans numpy.array et c# mais pas exactement les mêmes.

Dans un premier temps, une astuce Zip simple suffira:

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 le résultat:

[[1, 2], [7, 8], [3, 4], [5, 6], [9, 10]]
[2, 8, 4, 6, 10]

Trouvez-le un peu gênant. Et il faut aussi une liste supplémentaire.

26
clwen

Étant donné la relation illustrée dans la question, je suppose 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 index:

Pour Python2.x:

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])

Pour Python 3.x:

from random import shuffle
# Given list1 and list2
list1_shuf = []
list2_shuf = []
index_shuf = list(range(len(list1)))
shuffle(index_shuf)
for i in index_shuf:
    list1_shuf.append(list1[i])
    list2_shuf.append(list2[i])
39
kojiro

Si vous souhaitez installer quelques paquets supplémentaires:

Demande: NumPy (> = 1.6.1), SciPy (> = 0.9).

pip installer -U scikit-learn

from sklearn.utils import shuffle
list_1, list_2 = shuffle(list_1, list_2)
19
Tihomir Nedev

Si vous devez le faire souvent, vous pouvez envisager d’ajouter un niveau d’indirection en brassant 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
6
Jeremy Brown

Jusqu'ici, toutes les solutions ont créé de nouvelles listes afin de résoudre le problème. Si les listes a et b sont très longues, vous pouvez les mélanger. Pour cela, vous aurez 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 = [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]
2
AlexConfused

Une réponse rapide en utilisant numpy s'il vous plaît se 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]
1
Ryszard Cetnarski

Je ne sais pas s'il me manque quelque chose ici, mais il semblerait que vous ne fassiez que brouiller l'une 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 faire cela sans le rendre plus compliqué. Si vous souhaitez suivre la voie compliquée, vous pouvez simplement mélanger 1 liste et utiliser la liste non mélangée pour faire une recherche dans la liste mélangée et la réorganiser de cette manière. En fin de compte, vous obtenez le même résultat que vous avez commencé. Pourquoi la création d'une troisième liste pose-t-elle 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. 

0
minhaz1