Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating all possible combinations of characters in a string

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.

like image 865
James LT Avatar asked Aug 31 '17 21:08

James LT


Video Answer


3 Answers

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
like image 79
cs95 Avatar answered Sep 28 '22 01:09

cs95


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.

like image 36
MSeifert Avatar answered Sep 27 '22 23:09

MSeifert


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]
like image 22
linda Avatar answered Sep 27 '22 23:09

linda