[英]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代碼背景。
我嘗試了使用map
和lambda
的更多Pythonic解決方案:
[ map(lambda x,y: x+'-'+y, a,b) for a,b in zip(ls1,ls2) ]
但是我真的不知道我在做什么。
用Python的方式可以實現嵌套for
循環的目的是什么?
您可以將itertools.product
與map
一起使用:
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
那個將不起作用,因為您想要ls1
和ls2
所有元素對,但是zip
只是使用對應的元素而不是所有組合來創建對。
如果您想使用更緊湊的代碼,則可以使用適當的列表理解
ls3 = [x+'-'+y for x in ls1 for y in ls2]
對於大型列表,或需要任何性能表現的地方(這永遠不是您的首要考慮),請參閱@PaulPanzer的答案,他解釋了一種更高效但稍微復雜的技術。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.