在Python中随机交错两个数组

15

假设我有两个数组:

a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]

我希望将这两个数组交错到变量'c'中(请注意'a'和'b'的长度不一定相等),但我不希望它们以确定的方式交错。简而言之,仅仅使用zip这两个数组是不够的。我不希望:

c = [1, 5, 2, 6, 3, 7, 4, 8, 9]

相反,我想要一些随机的东西,比如:

c = [5, 6, 1, 7, 2, 3, 8, 4, 9]

还需要注意,'a'和'b'的顺序在生成的数组'c'中保留。

我当前的解决方案需要使用for循环和一些随机数生成。我不喜欢它,希望有人能指点我一个更好的解决方案。

# resulting array
c = []

# this tells us the ratio of elements to place in c. if there are more elements 
# in 'a' this ratio will be larger and as we iterate over elements, we will place
# more elements from 'a' into 'c'.
ratio = float(len(a)) / float(len(a) + len(b))

while a and b:
    which_list = random.random()
    if which_list < ratio:
        c.append(a.pop(0))
    else:
        c.append(b.pop(0))

# tack on any extra elements to the end
if a:
    c += a
elif b:
    c += b

但是您只想随机交错还是整个数组?我的意思是,您需要保留原始数组的顺序吗? - C2H5OH
4
你对它有什么不喜欢的地方?你需要生成随机数,虽然可以用列表推导式替换许多循环,但这有什么意义呢? - James Thiele
1
是的,这对我来说看起来完全没问题。 我相信你可以写出更紧凑的代码,但“简单胜于复杂”。 - ludaavics
@JamesThiele 我在Python方面仍然是个新手,所以我一直在寻找让我的代码更具Python风格的方法。 - salil
4
除了有趣的 Python 之外,你真的需要考虑接下来应该做什么。如果你已经选择了1、2、3,那么下一个选择应该是50%的4 / 50%的5(即使按列表排序),还是在未选中的项目列表a中加权为16%的4和84%的5,与列表b中未选中的5个项目相比。 - Charles Merriam
显示剩余2条评论
15个回答

0
我已经改编了@NPE's solution,使其在常数时间内删除空迭代器而不是线性时间。它可以接受任意数量的输入列表,并返回一个随机交错它们的迭代器,保留输入列表给定的顺序。
def interleave(*args):
  iters = [iter(x) for x in args]
  while iters:
    i = random.randrange(len(iters))
    try:
      yield next(iters[i])
    except StopIteration:
      # swap empty iterator to end and remove
      iters[i],iters[-1] = iters[-1],iters[i]
      iters.pop()

print list(interleave(xrange(1, 5), xrange(5, 10), xrange(10, 15)))

总运行时间为O(N)而不是O(N+M^2),其中N是项目的总数,M是列表的数量。


0
你可以像这样做:
(L, l) = (a, b) if len(a) > len(b) else( b, a)
positions = random.sample(range(len(L)), len(l))
for i in range(len(positions)):
    L.insert(positions[i], l[i])

但在我谦虚的意见中,你所拥有的是完全可以的。它能够工作,而且很简单。


0
这个想法怎么样:
import random as rn

a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]
n = 100 #Here i am picking an arbitrary number, it should probably be a function of 
        # lengths of a and b


a_ind = sorted(rn.sample(range(n),len(a))) #sorting the indexes insures that order of 
b_ind = sorted(rn.sample(range(n),len(b))) # a and b is preserved

big_list = zip(a,a_ind) + zip(b,b_ind)

big_list.sort(key  = lambda k: k[1])

result = list(zip(*big_list)[0])

结果:

>>> result
[1, 5, 2, 6, 3, 7, 8, 9, 4]

0

可能非常低效,但另一种可行的方法是:

import random

def interleave(*args):
    indices=[(i,j) for i in range(len(args)) for j in range(len(args[i]))]
    random.shuffle(indices)
    indices.sort(key=lambda x:x[1])
    return [args[i][j] for i,j in indices]

-1

描述中的“交错”一词可能会让人感到困惑。如果您只是将输入列表相加,然后对结果进行洗牌,您将得到相同的结果。只有在需要保留交错结果时才需要交错。

一些代码:

>>> import random
>>> 
>>> a, b = [1,2,3,4], [5,6,7,8]
>>> c = sum([a,b], [])
>>> random.shuffle(c)
>>> c
[6, 5, 8, 2, 7, 4, 1, 3] 

1
顺序很重要(我用完全相同的响应得到了完全相同的答案)。 - TryPyPy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接