他のリストの対応を壊すことなく、2つの関連リストをランダムにシャッフルするより良い方法はありますか?関連する質問をnumpy.array
とc#
で見つけましたが、まったく同じではありません。
最初の試みとして、単純な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]
少しぎこちないところを見つけてください。また、追加のリストも必要です。
質問で示された関係を考えると、リストは同じ長さであり、それをlist1[i]
に対応 list2[i]
任意のインデックス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)。
pip install -U scikit-learn
from sklearn.utils import shuffle
list_1, list_2 = shuffle(list_1, list_2)
これを頻繁に行う必要がある場合は、インデックスのリストをシャッフルして、1レベルの間接参照を追加することを検討できます。
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
これまでのところ、すべてのソリューションは問題を解決するために新しいリストを作成しました。リストaおよびbが非常に長い場合は、それらを所定の位置に入れ替えることができます。そのためには、次のような関数が必要です。
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つをシャッフルしているだけで、他のリストは最初のリストの順序と一致するように再配置されているようです。だからあなたが持っているものは、これをより複雑にすることなくこれを行う最良の方法です。複雑なルートをたどる場合は、1つのリストをシャッフルし、シャッフルされていないリストを使用してシャッフルされたリストを検索し、そのように並べ替えることができます。最終的には、最初と同じ結果になります。 3番目のリストの作成がなぜ問題になるのですか?リストを本当にリサイクルしたい場合は、リストbをリストcに使用しているものに置き換え、後でaとbに分離することができます。