簡體   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