Say I have a string list:
li = ['a', 'b', 'c']
I would like to construct a new list such that each entry of the new list is a concatenation of a selection of 3 entries in the original list. Note that each entry can be chosen repeatedly:
new_li=['abc', 'acb', 'bac', 'bca', 'cab', 'cba', 'aab', 'aac',....'aaa', 'bbb', 'ccc']
The brutal force way is to construct a 3-fold nested for loop and insert each 3-combination into the new list. I was wondering if there is any Pythonic way to deal with that? Thanks.
Update: Later I will convert the new list into a set, so the order does not matter anyway.
This looks like a job for itertools.product
.
import itertools
def foo(l):
yield from itertools.product(*([l] * 3))
for x in foo('abc'):
print(''.join(x))
aaa
aab
aac
aba
abb
abc
aca
acb
acc
baa
bab
bac
bba
bbb
bbc
bca
bcb
bcc
caa
cab
cac
cba
cbb
cbc
cca
ccb
ccc
yield from
is available to you from python3.3 and beyond. For older version, yield
within a loop:
def foo(l):
for i in itertools.product(*([l] * 3)) :
yield i
The best way to get all combinations (also called cartesian product) of a list is to use itertools.product
using the len
of your iterable as repeat
argument (that's where it differs from the other answer):
from itertools import product
li = ['a', 'b', 'c']
for comb in product(li, repeat=len(li)):
print(''.join(comb))
or if you want the result as list:
>>> combs = [''.join(comb) for comb in product(li, repeat=len(li))]
>>> combs
['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa',
'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab',
'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']
It's a bit cleaner to use the repeat
argument than to multiply and unpack the list you have manually.
An alternate approach using list comprehension:
li = ['a', 'b', 'c']
new_li = [a+b+c for a in li for b in li for c in li]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With