38

有没有更好的方法来随机打乱两个相关列表而不破坏它们在另一个列表中的对应关系?我在其中找到了相关的问题numpy.arrayc#但并不完全相同。

作为第一次尝试,一个简单的zip技巧就可以了:

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

它将得到输出:

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

就是觉得有点别扭。它还需要一个额外的列表。

4

7 回答 7

51

鉴于问题中展示的关系,我将假设列表的长度相同,并且list1[i]对应list2[i]于任何 index i。有了这个假设,改组列表就像改组索引一样简单:

 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])
于 2012-08-01T18:15:54.930 回答
33

如果您愿意安装更多软件包:

要求: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)
于 2017-01-14T10:47:21.030 回答
6

如果您必须经常这样做,您可以考虑通过改组索引列表来添加一个间接级别。

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
于 2012-08-01T18:16:48.600 回答
3

到目前为止,所有解决方案都创建了新列表以解决问题。如果列表ab很长,您可能需要将它们打乱。为此,您需要一个函数,例如:

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]
于 2018-04-17T16:36:35.877 回答
2

使用 numpy 的快速答案请参考这里
您可以使用

p = numpy.random.permutation(len(a))

为两个列表创建一个新的索引列表并使用它重新排序它们。

在您的场景中:

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]
于 2016-09-18T10:02:17.280 回答
0

您可以在最后解压缩以减少尴尬吗?

import numpy as np
list1 = [1,2,3]
list2 = [4,5,7]
list_zipped = list(zip(list1,list2))
np.random.shuffle(list_zipped)
list1,list2 = zip(*z) #unzipping
于 2019-10-16T09:56:52.383 回答
-1

我不确定我是否在这里遗漏了一些东西,但看起来你只是在洗牌其中一个列表,另一个重新排列以匹配第一个列表的顺序。所以你所拥有的是最好的方法来做到这一点,而不会使它变得更复杂。如果你想走复杂的路线,你可以只打乱 1 个列表并使用未打乱的列表在打乱的列表中进行查找并以这种方式重新排列。最后,您会得到与开始时相同的结果。为什么创建第三个列表是个问题?如果您真的想回收列表,那么您可以简单地将列表 b 替换为您用于列表 c 的内容,然后稍后将其分离回 a 和 b。

于 2012-08-01T18:17:29.920 回答