Joel Smith
Joel Smith

Reputation: 867

Need to Create a new Python List with all possible unique combinations of another list

I currently have a list of choices:

a = ['D1', 
    'C1', 
    'D2', 
    'C2', 
    'D3', 
    'C3', 
    'D4', 
    'C4', 
    'D5', 
    'C5',]

I want a new list with nested lists inside of possible combinations. Like this:

b = [
'D1', 
'C1', 
'D2', 
'C2', 
'D3', 
'C3', 
'D4', 
'C4', 
'D5', 
'C5',
['D1', 'C1'], 
['D1', 'D2'], 
['D1', 'C2'] 
.
. 
['D1', 'C1', 'D2'] 
.
. 
['D1', 'C1', 'D2', 'C2'] 
.
. 
['D1', 'C1', 'D2', 'C2', 'D3']
:
etc

Upvotes: 1

Views: 571

Answers (4)

martineau
martineau

Reputation: 123473

You can create a new list using itertools.combinations in conjunction with a very efficient and relatively succinct construct called a list comprehension. However for doing this it got a little complicated partially by the fact that not all of the items in the final list are themselves not nested lists. I actually suspect having it that way will make it harder for you to process the list later on, but, regardless, here's the simplest implementation I've been able to devise which produces exactly the list you said you wanted:

from itertools import combinations

a = ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']
b = [item for sublist in (list(combo[0] if len(combo) < 2 else list(combo)
                               for combo in combinations(a, n))
                                   for n in range(1, len(a)+1)) for item in sublist]

from pprint import pprint  # print the result
print 'b = \\'
pprint(b[:14] + ['... lines omitted ...'] + b[-14:])

Output:

b = \
['D1',
 'C1',
 'D2',
 'C2',
 'D3',
 'C3',
 'D4',
 'C4',
 'D5',
 'C5',
 ['D1', 'C1'],
 ['D1', 'D2'],
 ['D1', 'C2'],
 ['D1', 'D3'],
 '... lines omitted ...',
 ['C1', 'D2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['C1', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5'],
 ['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']]

Upvotes: 2

Grijesh Chauhan
Grijesh Chauhan

Reputation: 58271

You need actually power set of a here is my solution:

def powerset(seq):
    """
    Returns all the subsets of this set. This is a generator.
    """
    if len(seq) <= 1:
        yield seq
        yield []
    else:
        for item in powerset(seq[1:]):
            yield [seq[0]]+item
            yield item

a =['D1', 'C1', 'D2', 'C2', 'D3', 'C3', 'D4', 'C4', 'D5', 'C5']
b = [x for x in powerset(a)]
b.sort(key = len)
for x in b:
 print x

my refrence site: And Its working you can see at codepade here

EDIT a instance of run.

a =['D1', 'C1', 'D2']
b = [x for x in powerset(a)]
b.sort(key = len)
for x in b:
  print x

And its output:

[]
['D2']
['C1']
['D1']
['C1', 'D2']
['D1', 'D2']
['D1', 'C1']
['D1', 'C1', 'D2']

You can find Better code for Powerset in Python from following links.

http://docs.python.org/2/library/itertools.html
http://mail.python.org/pipermail/tutor/2004-April/029413.html
http://ruslanspivak.com/2011/06/09/power-set-generation-a-joy-of-python/

Although Mr.martineau given small and fast code but I don't understand itertools yet.

Upvotes: 2

Rushy Panchal
Rushy Panchal

Reputation: 17532

I suggest using itertools.permutations(a).

import itertools
a = ['D1', 
    'C1', 
    'D2', 
    'C2', 
    'D3', 
    'C3', 
    'D4', 
    'C4', 
    'D5', 
    'C5',]

b = list(itertools.permutations(a)) # this gives permutations of the same length

If you want ALL the possible permutations (of varying lengths), you can use a for loop:

b = []
for i in range(1, len(a)+1):
    b.extend(list(itertools.permutations(a, i)))

Put that into a list comprehension:

b = [list(itertools.permutations(x, i)) for i in range(1, len(x)+1)]

Upvotes: 1

bereal
bereal

Reputation: 34282

Check out itertools.combinations:

b = []
for len_ in xrange(len(a)):
    b.extend(itertools.combinations(a, len_+1)

See also the powerset recipe from the itertools docs:

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

Upvotes: 2

Related Questions