[Python-ideas] Another "little" combination, permutation, iterator, yield from, example.

Ron Adam ron3200 at gmail.com
Tue Oct 15 22:03:59 CEST 2013


On 10/13/2013 02:02 PM, Tim Peters wrote:> [MRAB, posts a beautiful solution]
 >
 > I don't really have a use for this, but it was a lovely programming
 > puzzle, so I'll include an elaborate elaboration of MRAB's algorithm
 > below.  And that's the end of my interest in this;-)

A what the heck...  :-)


This is what I came up with which works like MRAB's by removing the first 
element and using recursion on the rest.  (It's how you do it in lisp or 
scheme.)

It's just two generators working together.

You can get items with specified length by using a list comprehension or 
filter.

(Disclaimer... I didn't do any more testing (performance or otherwise)
  than you see below.)

Cheers,
    Ron Adam


def combine_with_all(x, seq):
     """Combine item x to every item in seq."""
     for s in seq:
       if (not (isinstance(s, list))):
         s = [s]
       yield s + [x]

def unique_sets(seq):
     """Return all unique combinations of elements in seq."""
     if len(seq) == 0:
         return []
     first, rest = seq[0], seq[1:]
     yield [first]
     yield from unique_sets(rest)
     yield from combine_with_all(first, unique_sets(rest))



### EXAMPLES ###

for args in [('x', []),
              ('x', [1, 2]),
              ('x', [[1], [2]]),
              ('x', [[1, 2], 3]),
              ('x', [[1, 2], [3]]),
              ('x', ['abc']),
              ('x', ['ab', 'c'])]:
     print(list(combine_with_all(*args)))

#  []
#  [[1, 'x'], [2, 'x']]
#  [[1, 'x'], [2, 'x']]
#  [[1, 2, 'x'], [3, 'x']]
#  [[1, 2, 'x'], [3, 'x']]
#  [['a', 'x'], ['b', 'x'], ['c', 'x']]
#  [['abc', 'x']]
#  [['ab', 'x'], ['c', 'x']]


print(list(unique_sets('abc')))
#  [['a'], ['b'], ['c'], ['c', 'b'], ['b', 'a'], ['c', 'a'],
#   ['c', 'b', 'a']]

print(list(unique_sets(['abc'])))
#  [['abc']]

print(list(unique_sets(['a', 'b', 'c']) ))
#  [['a'], ['b'], ['c'], ['c', 'b'], ['b', 'a'], ['c', 'a'],
#   ['c', 'b', 'a']]

print(list (unique_sets( [(1,2), (3,4)] )))
#  [[(1, 2)], [(3, 4)], [(3, 4), (1, 2)]]

print(list (unique_sets( [[1,2], [3,4]] )))
#  [[[1, 2]], [[3, 4]], [[3, 4], [1, 2]]]

print([x for x in unique_sets(['a', 'b', 'c']) if len(x) == 2])
#  [['c', 'a'], ['b', 'a'], ['c', 'b']]

print([x for x in unique_sets(["a1", "b", "a2"]) if len(x) == 2])
#  [['a2', 'b'], ['b', 'a1'], ['a2', 'a1']]





More information about the Python-ideas mailing list