4

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.

ibi0tux
  • 2,481
  • 4
  • 28
  • 49
  • 1
    I don't think you're reducing a list here, rather your outputting various permutations. – msvalkon Jun 17 '13 at 08:31
  • You're not very comfortable means it does not work, or it simply does not look nice to you? – Rubens Jun 17 '13 at 08:32
  • It means, i know how it works, i prefer using such functions when it is possible, but i still have difficulties to use it. – ibi0tux Jun 17 '13 at 08:33
  • 2
    You're looking for powersets, see the recipe on the itertools page: http://docs.python.org/2/library/itertools.html – georg Jun 17 '13 at 08:37

2 Answers2

3

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']
juniper-
  • 6,262
  • 10
  • 37
  • 65
3

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']
TerryA
  • 58,805
  • 11
  • 114
  • 143