【问题标题】:Better way to shuffle two related lists打乱两个相关列表的更好方法
【发布时间】:2012-07-30 16:36:59
【问题描述】:

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

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

【问题讨论】:

  • 你也可以使用zip解压列表:a,b = zip(*c)
  • 我通常也不推荐您需要保留一组并行列表的程序设计。只需保留 1 个列表。创建某种类或其他东西来统一您的数据。
  • 如果想通过numpy做这样的工作,这里有一个很好的解决方案:stackoverflow.com/questions/4601373/…

标签: python list shuffle


【解决方案1】:

鉴于问题中展示的关系,我将假设列表长度相同,并且对于任何索引 ilist1[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])

【讨论】:

  • 作为列表推导的粉丝:list1_shuf = [list1[i] for i in index_shuf]
  • @kojiro:没关系:nappend_ops + nappend_ops = n*(append_ops+append_ops) = 2*n*append_ops
【解决方案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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      使用 numpy 的快速解答请参考here:
      你可以使用

      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]
      

      【讨论】:

        【解决方案5】:

        如果你愿意多安装几个包:

        要求: 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)
        

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

            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
            

            【讨论】:

              猜你喜欢
              • 2011-06-03
              • 2014-10-03
              • 1970-01-01
              • 2020-03-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-29
              相关资源
              最近更新 更多