3

How do I generate

[(0,), (1,), (2,), (0,1), (0,2), (1,2), (0,1,2)]

programmatically (that is, without writing everything out by hand)? That is, a list of all nonempty subtuples of the tuple (0,1,2).

(Note this is not asking for subsets but subtuples.)

3 Answers3

5
>>> from itertools import combinations
>>> t = (0, 1, 2)
>>> print [subset for r in range(1,4) for subset in itertools.combinations(t,r)]
[(0,), (1,), (2,), (0, 1), (0, 2), (1, 2), (0, 1, 2)]

Itertools is a powerful resource. You should check out the documentation

chepner
  • 497,756
  • 71
  • 530
  • 681
David Greydanus
  • 2,551
  • 1
  • 23
  • 42
4

You can use the powerset() recipe and remove the empty set:

from itertools import chain, combinations

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))

as follows:

In [3]: [ss for ss in powerset([0,1,2]) if ss]
Out[3]: [(0,), (1,), (2,), (0, 1), (0, 2), (1, 2), (0, 1, 2)]
xnx
  • 24,509
  • 11
  • 70
  • 109
  • Aside from any details regarding order, I need usually the powerset without the empty set and without the full set - so I use the `recipe` above but use `range(1,len(s))` - not sure it is bulletproof... – nate Feb 02 '18 at 22:36
  • 1
    @nate I think this is safe: letting `r` range between `1` and `n-1` inclusive omits the empty set and the full set from the call to `combinations`. – xnx Feb 03 '18 at 09:36
2

What you want is basically powerset but without the empty set. By modifying the recipe from the python itertools page to start with a combinations size of 1:

from itertools import combinations, chain

def almost_powerset(seq):
    return list(chain.from_iterable(combinations(seq, r) 
                for r in range(1, len(seq)+1)))

and then just pass in your sequence

lst = [0, 1, 2]
res = almost_powerset(lst)

This generates all the combinations of size 1, then size 2, etc, up to the total length of your sequence, then uses chain to connect them.

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174