繁体   English   中英

洗牌两个相关列表的更好方法

[英]Better way to shuffle two related lists

有没有更好的方法来随机洗牌两个相关列表而不破坏它们在另一个列表中的对应关系? 我在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

它将获得 output:

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

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

给定问题中证明的关系,我将假定列表的长度相同,并且任何索引i list1[i]对应于list2[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])

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

要求:NumPy(> = 1.6.1),SciPy(> = 0.9)。

点安装-U scikit-learn

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

如果必须经常执行此操作,则可以考虑通过改组索引列表来添加一个间接级别。

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

到目前为止,所有解决方案都创建了新列表以解决该问题。 如果列表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]

使用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]

您可以在最后进行解压缩以限制尴尬吗?

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

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

AlexConfused 方法的修改版本,更通用,可以直接复制和使用:

from random import shuffle, getstate, setstate


def shuffle_inplace(lst, state):
    """ shuffle multiple lists in-place using order determined by state """
    setstate(state)
    shuffle(lst)


lst1 = [0, 1, 2, 3, 4]
lst2 = [5, 6, 7, 8, 9]

s = getstate()
shuffle_inplace(lst1, s)
shuffle_inplace(lst2, s)

print(lst1)
print(lst2)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM