有没有更聪明的方法在Python中合并这两个列表?

我有两个列表,我正在尝试用它们创建一个大列表。第一个列表只是给了我每个父母可以拥有的所有可能的孩子数量。把它想象成标签。

num_of_children = [0, 1, 2, 3, 4, 5]

第二个列表告诉我有多少父母有多少孩子。例如,27 个父母有 0 个孩子,其中 22 个有 1 个,依此类推。

number_of_parents = [27, 22, 30, 12, 7, 2]

使用这两个列表,我试图获得一个如下所示的列表:

parent_num_of_children = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 
3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5]

到目前为止,我能够做到这一点:

for number in num_of_children:
    parent_num_of_children.extend([number] * number_of_parents[number])

我的问题是:是否有另一种方法可以在没有 for 循环的情况下获取此列表,只需使用 range 函数或其他聪明的方法?

感谢您的回答!

回答

有一些itertools

list(chain.from_iterable(map(repeat, num_of_children, number_of_parents)))

基准:

0.23 s  0.35 s  0.33 s  original
0.67 s  0.64 s  0.72 s  Bram_Vanroy
1.36 s  1.48 s  1.52 s  Fredericka
0.29 s  0.35 s  0.34 s  superb_rain

在最后查看更多基准。

代码:

import timeit
from itertools import chain, repeat

def original(num_of_children, number_of_parents):
    parent_num_of_children = []
    for number in num_of_children:
        parent_num_of_children.extend([number] * number_of_parents[number])
    return parent_num_of_children

def Bram_Vanroy(num_of_children, number_of_parents):
    return [c for c, p in zip(num_of_children,number_of_parents) for _ in range(p)]

def Fredericka(num_of_children, number_of_parents):
    parent_num_of_children = []
    for i in range(len(number_of_parents)):
        for n in range(number_of_parents[i]):
            parent_num_of_children.append(num_of_children[i])
    return parent_num_of_children

def superb_rain(num_of_children, number_of_parents):
    return list(chain.from_iterable(map(repeat, num_of_children, number_of_parents)))

funcs = original, Bram_Vanroy, Fredericka, superb_rain
num_of_children = [0, 1, 2, 3, 4, 5]
number_of_parents = [27, 22, 30, 12, 7, 2]

# Correctness
expect = original(num_of_children, number_of_parents)
for func in funcs:
    result = func(num_of_children, number_of_parents)
    print(result == expect, func.__name__)
print()

# Speed
tss = [[] for _ in funcs]
for _ in range(4):
    for func, ts in zip(funcs, tss):
        t = min(timeit.repeat(lambda: func(num_of_children, number_of_parents), number=100000))
        ts.append(t)
        print(*('%.2f s ' % t for t in ts[1:]), func.__name__)
    print()

另一个基准,具有“更大”的情况num_of_children = [0, 1, 2, 3, 4, 5] * 100number_of_parents = [27, 22, 30, 12, 7, 2] * 100(和number=1000):

0.25 s  0.17 s  0.16 s  original
0.57 s  0.41 s  0.40 s  Bram_Vanroy
1.22 s  1.19 s  1.17 s  Fredericka
0.16 s  0.16 s  0.17 s  superb_rain

另一个,我改为使用number_of_parents = [p * 100 for p in number_of_parents](和再次number=1000)增加值:

0.09 s  0.09 s  0.09 s  original
0.46 s  0.38 s  0.38 s  Bram_Vanroy
1.27 s  1.56 s  1.22 s  Fredericka
0.07 s  0.07 s  0.09 s  superb_rain

并使用@BramVanroy 的评论建议的数据,num_of_children = [i for i in range(100)]; number_of_parents = [random.randint(500,1000) for _ in range(100)](和number=100):

0.06 s  0.05 s  0.05 s  original
0.27 s  0.25 s  0.25 s  Bram_Vanroy
0.91 s  0.89 s  0.90 s  Fredericka
0.05 s  0.05 s  0.05 s  superb_rain


以上是有没有更聪明的方法在Python中合并这两个列表?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>