有没有更聪明的方法在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] * 100和number_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