ibi0tux
ibi0tux

Reputation: 2629

Python, recursively reduce a list (combinations/permutations)

I'm trying to make a generic function that would reduce a list like so :

func(['a','b','c'],str.join) # --> ['a','b','c','ab','ac','bc','abc']

func(['a','b','c'],lambda: a,b:a+'x'+b) # --> ['a','b','c','axb','axc','bxc','axbxc']

I don't really know how to do it. I did a few tries, but none was successful. I'm pretty sure there is a way to do it with reduce but i'm not very comfortable with the use of this function. Here are some attempts :

reduce(lambda a,b:[a,b,str(a)+str(b)],['a','b','c'])

reduce(str.join,['a','b','c'])

I think i'm missing a recursion somewhere.

I'm not asking for code especially, any help or advice is welcomed. Thanks.

Upvotes: 4

Views: 1404

Answers (2)

TerryA
TerryA

Reputation: 60014

How's this?

>>> import itertools
>>> def func(mylist, letter):
...     L = []
...     for i in range(len(mylist)):
...             L.append(list(itertools.combinations(mylist,i+1)))
...     return [letter.join(i) for i in itertools.chain.from_iterable(L)]
... 
>>> func(['a','b','c'], 'x')
['a', 'b', 'c', 'axb', 'axc', 'bxc', 'axbxc']

Upvotes: 3

juniper-
juniper-

Reputation: 6572

itertools.combinations will give you all combinations of a certain length. We take all the combinations for each possible sublist length. We then map the function you were interested in (the lambda function, or in this case "x".join) to each of the generated combinations.

>>> import itertools as it
>>> a = ['a','b','c']
>>> l = [map("x".join, list(it.combinations(a, l))) for l in range(1,len(a)+1)]
>>> l
[['a', 'b', 'c'], ['axb', 'axc', 'bxc'], ['axbxc']]

Now l is a list of lists that we want to flatten:

>>> [ x for y in l for x in y]
['a', 'b', 'c', 'axb', 'axc', 'bxc', 'axbxc']

Upvotes: 3

Related Questions