Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中随机交错2个数组_Python_Arrays_Random - Fatal编程技术网

在Python中随机交错2个数组

在Python中随机交错2个数组,python,arrays,random,Python,Arrays,Random,假设我有两个数组: a = [1, 2, 3, 4] b = [5, 6, 7, 8, 9] 我想将这两个数组交错到一个变量“c”(注意“a”和“b”的长度不一定相等),但我不希望它们以确定性的方式交错。简而言之,仅仅压缩这两个阵列是不够的。我不想: c = [1, 5, 2, 6, 3, 7, 4, 8, 9] 相反,我想要一些随机的东西,比如: c = [5, 6, 1, 7, 2, 3, 8, 4, 9] 还请注意,“a”和“b”的顺序保留在结果数组“c”中 我目前的解决方案需要一个

假设我有两个数组:

a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]
我想将这两个数组交错到一个变量“c”(注意“a”和“b”的长度不一定相等),但我不希望它们以确定性的方式交错。简而言之,仅仅压缩这两个阵列是不够的。我不想:

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
#结果数组
c=[]
#这告诉我们c中元素与位置的比率。如果有更多的元素
#在“a”中,这个比率将更大,当我们迭代元素时,我们将放置
#从“a”到“c”的更多元素。
比率=浮动(len(a))/浮动(len(a)+len(b))
而a和b:
哪个列表=random.random()
如果哪个列表<比率:
c、 附加(a.pop(0))
其他:
c、 附加(b.pop(0))
#在末端附加任何额外元素
如果是:
c+=a
elif b:
c+=b

编辑:我认为最近这一次最好:

a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]
c = [x.pop(0) for x in random.sample([a]*len(a) + [b]*len(b), len(a)+len(b))]
或者更有效地:

c = map(next, random.sample([iter(a)]*len(a) + [iter(b)]*len(b), len(a)+len(b)))
请注意,上面的第一个方法修改了原始列表(正如您的代码所做的),而第二个方法没有修改。在Python3.x上,您需要执行
list(map(…)
,因为
map
返回迭代器

下面的原始答案:

以下是一个可保存几行的选项:

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

c = []
tmp = [a]*len(a) + [b]*len(b)
while a and b:
    c.append(random.choice(tmp).pop(0))

c += a + b
这里还有另一个选项,但只有当您知道所有元素都不是falsy(无
0
'
None
False
,或空序列)时,它才会起作用:

a=[1,2,3,4]
b=[5,6,7,8,9]
比率=浮动(len(a))/浮动(len(a)+len(b))
c=[(非a和b.pop(0))或(非b和a.pop(0))或
(random.random()<比率和b.pop(0))或a.pop(0)
对于uu在范围内(len(a)+len(b))]

将一个标志数组串联起来,然后洗牌,然后用它来选择一个数组,从中提取每个项目,怎么样

import random

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

c = list('a' * len(a) + 'b' * len(b)) # Flags for taking items from each array
random.shuffle(c) # Randomize from where we take items

aa, bb = a[:], b[:] # Copy the arrays for popping 
d = [aa.pop(0) if source == 'a' else bb.pop(0) for source in c]
# Take items in order, randomly from each array
雾鸟更有效的方法:

c = [a[:]] * len(a) + [b[:]] * len(b)
random.shuffle(c) # Randomize from where we take items

d = [x.pop(0) for x in c] # Take items in order, randomly from each array

你可以这样做:

(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])
import random

LResult = []

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

while LLists[0] or LLists[1]:
    LResult.append(LLists[random.choice([int(len(LLists[0])==0), int(len(LLists[1])!=0)])].pop(0))
def selectFromTwoList(ratioFromList1):
    final_list = []
    for i in range(len(list1)):
        rand = random.randint(1, 100)
        if rand <= ratioFromList1*100:
            final_list.append(list1.pop(0))
        else:
            final_list.append(list2.pop(0))
        return final_list

但依我拙见,你所拥有的一切都很好。。这个解决方案提供了一个生成器,通过随机交换列表(a)和(b)中尚未发出的部分来工作

import random

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

def interleave(a,b):
   while a or b:
      (a,b)=(a,b) if len(a) and (random.random()<0.5 or not len(b)) else (b,a)
      yield a.pop(0)

print list(interleave(a,b))
随机导入
a=[1,2,3,4]
b=[5,6,7,8,9]
def交织(a、b):
而a或b:

(a,b)=(a,b)如果len(a)和(random.random(),这里有一些东西使用未记录的Python(具体地说,列表迭代器对象的
\uu length\u hint\uu
方法,它告诉你迭代器中还剩下多少项)将其塞进列表理解中。我想,更多的是为了好玩,而不是实际的实用性

itera, iterb = iter(a), iter(b)
morea, moreb = itera.__length_hint__, iterb.__length_hint__
c = [next(itera) if not moreb() or morea() and random.random() < ratio
     else next(iterb) for c in xrange(len(a) + len(b))]
itera,iterb=iter(a),iter(b)
morea,moreb=itera.\uuuuu长度\uuu提示\uuuuuuuuu,iterb.\uuuuuu长度\uu提示__
c=[next(itera)if not moreb()或morea()和random.random()<比率
else-next(iterb)表示x范围内的c(len(a)+len(b))]

编辑以消除多余的混乱:这里有一个解决方案,可以处理任意数量的输入列表,不会丢弃输入列表,也不会复制它们:

import random

def interleave(*args):
    iters = [i for i, b in ((iter(a), a) for a in args) for _ in xrange(len(b))]
    random.shuffle(iters)
    return map(next, iters)
Stackoverflow用户EOL提供了我的解决方案的增强版:

def interleave(*args):
    iters = sum(([iter(arg)]*len(arg) for arg in args), [])
    random.shuffle(iters)
    return map(next, iters)
$ python -m timeit -v -s "from srgerg import accepted" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "accepted(list(a), list(b))"
10 loops -> 10.5 secs
raw times: 10.3 10.1 9.94
10 loops, best of 3: 994 msec per loop
运行这个

a = [1,2,3,4]
b = [5,6,7,8,9]
print interleave(a, b)
产生以下可能结果之一:

[5, 6, 7, 1, 8, 2, 3, 9, 4]
编辑:应EOL的要求,我更新了计时代码。不幸的是,由于接受的解决方案修改了其输入,我需要在每次迭代时制作一份新的副本。我已经为F.J和我自己的解决方案做了这项工作,以使结果具有可比性。以下是F.Js解决方案的计时:

def interleave(*args):
    iters = sum(([iter(arg)]*len(arg) for arg in args), [])
    random.shuffle(iters)
    return map(next, iters)
$ python -m timeit -v -s "from srgerg import accepted" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "accepted(list(a), list(b))"
10 loops -> 10.5 secs
raw times: 10.3 10.1 9.94
10 loops, best of 3: 994 msec per loop
下面是我的函数版本的计时

$ python -m timeit -v -s "from srgerg import original" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "original(list(a), list(b))"
10 loops -> 0.616 secs
raw times: 0.647 0.614 0.641
10 loops, best of 3: 61.4 msec per loop
以下是EOL增强版的时间安排:

$ python -m timeit -v -s "from srgerg import eol_enhanced" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "eol_enhanced(list(a), list(b))"
10 loops -> 0.572 secs
raw times: 0.576 0.572 0.588
10 loops, best of 3: 57.2 msec per loop
如果我从EOL增强版的循环中删除列表复制,我会得到以下结果:

$ python -m timeit -v -s "from srgerg import eol_enhanced" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "eol_enhanced(a, b)"
10 loops -> 0.573 secs
raw times: 0.572 0.575 0.565
10 loops, best of 3: 56.5 msec per loop
另一个编辑:F.J有一个更新的解决方案,并要求我添加计时:

$ python -m timeit -v -s "from srgerg import fj_updated" -s "a = list(xrange(40000))" -s "b = list(xrange(60000))" "fj_updated(list(a), list(b))"
10 loops -> 0.647 secs
raw times: 0.652 0.653 0.649
10 loops, best of 3: 64.9 msec per loop
这个想法怎么样:

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]

根据TryPyPy的建议编辑:

from random import choice

l = [a, b]
c = [choice(l).pop(0) for i in range(len(a) + len(b)) if (a and b)] + a + b

以下是一个适用于任意数量iTerable的解决方案:

import random

def interleave(*args):
  iters = map(iter, args)
  while iters:
    it = random.choice(iters)
    try:
      yield next(it)
    except StopIteration:
      iters.remove(it)

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

<强> ps < /强>:<强>请考虑阅读< /强>:在我看来,最好的解决方案(虽然F.J比较接近)。与下面的解决方案相比,它更一般,甚至更简单,只需要大约两倍的内存。

这里有一些既简单又有效的东西:

[(a if random.randrange(0, len(a)+len(b)) < len(a) else b).pop(0) for _ in range(len(a)+len(b))]

描述中的“交错”一词可能会令人困惑。如果您只是简单地添加输入列表,然后对结果进行洗牌,则会得到相同的结果。只有在要保留交错结果的情况下,才需要交错

一些代码:

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

我会这样解决这个问题:

(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])
import random

LResult = []

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

while LLists[0] or LLists[1]:
    LResult.append(LLists[random.choice([int(len(LLists[0])==0), int(len(LLists[1])!=0)])].pop(0))
def selectFromTwoList(ratioFromList1):
    final_list = []
    for i in range(len(list1)):
        rand = random.randint(1, 100)
        if rand <= ratioFromList1*100:
            final_list.append(list1.pop(0))
        else:
            final_list.append(list2.pop(0))
        return final_list
LLists是一个多维列表,存储两个列表(示例中的a和b)。该语句相当于:LLists=[a[:],b[:],但是为了简单和清晰起见,我在列表中显式编码

LResult是示例中的c,最终存储生成的数组

while循环将循环,直到LLists sub 0和LLists sub 1都完全为空。在循环中,LResult将从LLists sub 0或LLists sub 1中追加一个值。选择子列表值的决定由随机.choice()语句决定,该语句取两个值(在本例中)参数,然后随机返回其中一个参数

提供给random.choice()的选项由LLists中每个子列表的长度决定。如果LLists sub 0的长度大于零,则选项号1由语句int(len(LLists[0])==0)返回为零。对于random.choice()的第二个选项,如果LLists sub 1的长度大于零,则返回语句int(len(LLists[1])!=0)将返回1。在这两种情况下,如果子列表的长度之一为零,则相应的语句