【问题标题】:Shuffling two lists separately in Python在 Python 中分别打乱两个列表
【发布时间】:2015-04-29 07:01:22
【问题描述】:

这是我的代码:

import random
from random import shuffle

a = ['a','b','c','d']
b = ['a','b','c','d']
c = ['w','x','y','z']
d = ['w','x','y','z']
indices = random.sample(range(len(a)), len(a))
a = map(a.__getitem__, indices)
b = map(b.__getitem__, indices)
shuffle(c)
shuffle(d)
print a,b,c,d

这段代码的作用是将 a 和 b 按相同的顺序打乱,并按自己的顺序打乱 c 和 d。我现在要做的是制作两个更长的列表,由 a 和 c、b 和 d 组成,并将它们按随机顺序排列。我想要的是 a 和 b 在列表中保持相同的顺序。有没有办法做到这一点?任何帮助将不胜感激。 :)

编辑:

我希望输出看起来像这样,其中列表 a&b 对应,而 c&d 只是独立随机化的。

['d','x','w','b','a','y','c','z']

['d','z','y','b','a','x','c','w']

【问题讨论】:

  • 请显示您正在寻找的输出示例。
  • 会做,我在上面加。
  • 您是否希望 a 和 b 在新的组合列表中不仅保持相同的顺序,而且保持相同的位置?例如,您的新列表是否可以是 ['a', 'b', 'c', 'd', 'w', 'x', 'y', 'z']['z', 'a', 'y', 'b', 'x', 'c', 'w', 'd'],其中 abcd 在两个列表中的相对顺序相同,但位置不同?
  • 另外,a/b 的元素是否总是与 c/d 的元素不同,或者两者都包含某些元素?
  • 如果ab的元素总是在同一个位置,可以对索引进行采样,例如random.sample(range(len(a)+len(c),4),并将a的四个元素放入组合列表在这些位置上,然后从左到右依次填写cd 中的位置。

标签: python list random shuffle


【解决方案1】:

如果我们首先对cd 进行洗牌,从acbd 串联的列表中随机抽样得到所需的结果(我使用的是Python 3,因此打印需要括号):

import random
from random import shuffle

a = ['a','b','c','d']
b = ['a','b','c','d']
c = ['w','x','y','z']
d = ['w','x','y','z']
shuffle(c)
shuffle(d)
# print a,b,c,d
print (a,b,c,d)
ac = a + c
bd = b + d
indices = random.sample(range(len(ac)),len(ac))
ac = list(map(ac.__getitem__, indices))
bd = list(map(bd.__getitem__, indices))
#print ac, bd
print (ac, bd)

输出如下:

['a', 'b', 'c', 'd'] ['a', 'b', 'c', 'd'] ['x', 'w', 'z', 'y']['y', 'z', 'w', 'x']
['y', 'z', 'c', 'x', 'b', 'w', 'd', 'a'] ['x', 'w', 'c', 'y', 'b', 'z', 'd', 'a']

编辑:

感谢@Jan-Philip Gehrcke 指出,当列表很大时,使用numpy 索引(如下)要快得多:

from random import shuffle
import numpy as np

a = ['a','b','c','d']
b = a[:]
c = ['w','x','y','z']
d = c[:]
shuffle(c)
shuffle(d)
# print a,b,c,d
print (a,b,c,d)
ac = np.array(a + c)
bd = np.array(b + d)
indices = list(range(len(ac)))
shuffle(indices)
ac = ac[indices]
bd = bd[indices]
#print ac, bd
print (ac, bd)

【讨论】:

  • 使用列表推导根据随机索引样本创建新列表更好,甚至在我的系统上稍微更快(阅读:它并不慢,所以使用更好的语法:-))。
  • 对应的基准代码:timeit.timeit("l2=[l[i] for i in idcs]", setup="from random import sample as s; N=10**6; idcs=s(range(N), N); l=list(range(N))", number=10) -- l2=[l[i] for i in idcs] 在我的系统上需要 2.14 秒,l2=list(map(l.__getitem__,idcs)) 需要 2.16 秒。
  • @Jan-PhilipGehrcke:我同意,如果是我的代码,我会使用列表理解。我在这种情况下使用了地图,因为 OP 在问题中使用了这种方法。
  • 另请注意,纯基于 numpy 的索引方法要快得多。与上述相同的基准,基于newarray = oldarray[randomindex] 的索引大约快 20 倍:>>> timeit.timeit("l2=l[idcs]", setup="import numpy as np; N=10**6; idcs=np.random.randint(0,N,N); l=np.array(list(range(N)))", number=10)
【解决方案2】:

这是一种方法:

a = ['a','b','c','d']
# make b later
c = ['w','x','y','z']
d = ['w','x','y','z']
random.shuffle(a)
random.shuffle(c)
random.shuffle(d)
b = list(a)

x = a + c
random.shuffle(x)

y = []
for item in x:
    if item in a:
        y.append(b.pop())
    else:
        y.append(d.pop())

>>> x
['w', 'z', 'b', 'x', 'c', 'd', 'a', 'y']
>>> y
['z', 'y', 'b', 'x', 'c', 'd', 'a', 'w']

如果您希望 a 和 b 具有相同的随机顺序,则只需将 a 洗牌,然后将 b 复制一份会更方便。然后为了制作新的列表 x 和 y,我首先通过改组 a + c 来制作 x,然后通过 x 构建 y 并添加来自 bd 的成员,具体取决于是否对应的元素xac 中。

这种方法假设 a 和 b 中的元素集与 c 和 d 中的元素不相交。当前版本还在创建y 的过程中破坏了 b 和 d,尽管这可以通过稍微繁琐的算法来解决(跟踪bd 中的索引并通过索引而不是弹出来抓取元素)。

【讨论】:

  • 您的if item in a 方法假定这些列表是不重叠的集合。此外,您基本上将c 洗牌两次。另外,比起b=list(a),我更喜欢b = a[:] :-)。
  • @Jan-PhilipGehrcke:是的,我在底部添加了一条注释来提及该假设。我喜欢list(a) 胜过a[:] :-)。
【解决方案3】:

先随机改组 c 然后压缩到 a 怎么样?

    import random
    a=['a','b','c','d']
    b=['a','b','c','d']
    c=['w','x','y','z']
    d=['w','x','y','z']
    random.shuffle(c)
    a_c = zip(a,c)
    print a_c

[('a', 'y'), ('b', 'z'), ('c', 'x'), ('d', 'w')]

列表 a 的顺序不变,而列表 c 随机打乱。 希望对您有所帮助。

【讨论】:

  • 我认为他希望ac 随机交错,而不是严格地将a 中的一个元素与c 中的一个元素交替。
猜你喜欢
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多