繁体   English   中英

在Python中明智地串联两个Strings元素列表,而没有嵌套的for循环

[英]Concatenating two lists of Strings element wise in Python without Nested for loops

我有两个字符串列表: ls1 = ['a','b','c','d']ls2 = ['k','j','l','m']

我想创建第三个列表: ls3 = ['a-k','a-j','a-l','a-m','b-k','b-j','b-l','b-m'...'d-m'] ,其中包含16个元素。

我可以使用以下嵌套的for循环轻松实现此目的

ls3 = [] 
for elem in ls1:
    for item in ls2:
        ls3.append(elem+'-'+item)

但是,这不是Python语言,它揭示了我的C代码背景。

我尝试了使用maplambda的更多Pythonic解决方案:

[ map(lambda x,y: x+'-'+y, a,b) for a,b in zip(ls1,ls2) ]

但是我真的不知道我在做什么。

用Python的方式可以实现嵌套for循环的目的是什么?

您可以将itertools.productmap一起使用:

list(map('-'.join, itertools.product('abcd', 'kjlm')))
# ['a-k', 'a-j', 'a-l', 'a-m', 'b-k', 'b-j', 'b-l', 'b-m', 'c-k', 'c-j', 'c-l', 'c-m', 'd-k', 'd-j', 'd-l', 'd-m']

测试正确性和时机:

适用于基准的通常免责声明。

在测试条件下,上述解决方案(“ product map ”)的解决方案比“纯朴的”列表理解(“ naive ”)解决方案要快,尽管对于小问题大小而言,裕度很小。

提速的大部分似乎是由于避免了列表理解。 事实上,如果map是由列表理解(“替换product compr ”),则product仍鳞比天真的方法比较好,但小问题尺寸落后:

small (4x4)
results equal: True True
naive             0.002420 ms
product compr     0.003211 ms
product map       0.002146 ms
large (4x4x4x4x4x4)
results equal: True True
naive             0.836124 ms
product compr     0.681193 ms
product map       0.385240 ms

基准脚本供参考

import itertools
import timeit

lists = [[chr(97 + 4*i + j) for j in range(4)] for i in range(6)]

print('small (4x4)')
print('results equal:', [x+'-'+y for x in lists[0] for y in lists[1]]
      ==
      list(map('-'.join, itertools.product(lists[0], lists[1]))), end=' ')
print(['-'.join(t) for t in  itertools.product(lists[0], lists[1])]
      ==
      list(map('-'.join, itertools.product(lists[0], lists[1]))))

print('{:16s} {:9.6f} ms'.format('naive', timeit.timeit(lambda: [x+'-'+y for x in lists[0] for y in lists[1]], number=1000)))
print('{:16s} {:9.6f} ms'.format('product compr', timeit.timeit(lambda: ['-'.join(t) for t in itertools.product(lists[0], lists[1])], number=1000)))
print('{:16s} {:9.6f} ms'.format('product map', timeit.timeit(lambda: list(map('-'.join, itertools.product(lists[0], lists[1]))), number=1000)))

print('large (4x4x4x4x4x4)')
print('results equal:', ['-'.join((u, v, w, x, y, z)) for u in lists[0] for v in lists[1] for w in lists[2] for x in lists[3] for y in lists[4] for z in lists[5]]
      ==
      list(map('-'.join, itertools.product(*lists))), end=' ')
print(['-'.join(t) for t in  itertools.product(*lists)]
      ==
      list(map('-'.join, itertools.product(*lists))))

print('{:16s} {:9.6f} ms'.format('naive', timeit.timeit(lambda: ['-'.join((u, v, w, x, y, z)) for u in lists[0] for v in lists[1] for w in lists[2] for x in lists[3] for y in lists[4] for z in lists[5]], number=1000)))
print('{:16s} {:9.6f} ms'.format('product compr', timeit.timeit(lambda: ['-'.join(t) for t in  itertools.product(*lists)], number=1000)))
print('{:16s} {:9.6f} ms'.format('product map', timeit.timeit(lambda: list(map('-'.join, itertools.product(*lists))), number=1000)))

您所使用的技术完全是Python风格的,并且直到将列表理解引入该语言之前,都是规范的。 但是,您建议使用zip那个将不起作用,因为您想要ls1ls2所有元素对,但是zip只是使用对应的元素而不是所有组合来创建对。

如果您想使用更紧凑的代码,则可以使用适当的列表理解

ls3 = [x+'-'+y for x in ls1 for y in ls2]

对于大型列表,或需要任何性能表现的地方(这永远不是您的首要考虑),请参阅@PaulPanzer的答案,他解释了一种更高效但稍微复杂的技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM