web-dev-qa-db-ja.com

2つの関連リストをシャッフルするより良い方法

他のリストの対応を壊すことなく、2つの関連リストをランダムにシャッフルするより良い方法はありますか?関連する質問を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]

少しぎこちないところを見つけてください。また、追加のリストも必要です。

33
clwen

質問で示された関係を考えると、リストは同じ長さであり、それを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])
43
kojiro

さらにいくつかのパッケージをインストールする場合:

必須: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)
20
Tihomir Nedev

これを頻繁に行う必要がある場合は、インデックスのリストをシャッフルして、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
6
Jeremy Brown

これまでのところ、すべてのソリューションは問題を解決するために新しいリストを作成しました。リスト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]
2
AlexConfused

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

最後に解凍して、ぎこちなさを少し制限できますか?

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
0
Arun

ここに何か欠落しているかどうかはわかりませんが、リストの1つをシャッフルしているだけで、他のリストは最初のリストの順序と一致するように再配置されているようです。だからあなたが持っているものは、これをより複雑にすることなくこれを行う最良の方法です。複雑なルートをたどる場合は、1つのリストをシャッフルし、シャッフルされていないリストを使用してシャッフルされたリストを検索し、そのように並べ替えることができます。最終的には、最初と同じ結果になります。 3番目のリストの作成がなぜ問題になるのですか?リストを本当にリサイクルしたい場合は、リストbをリストcに使用しているものに置き換え、後でaとbに分離することができます。

0
minhaz1