combinations of variable length nested lists
Tim Peters
tim.one at home.com
Tue Aug 7 20:30:27 EDT 2001
[Mark Robinson]
> ...
> I have a nested list structure of the following format:
> [[2, 3, 4, 5],
> [4, 5, 6, 7, 34],
> [6, 2, 7, 4]
> ....
> ....
> ]
>
> I want to generate all possible combinations that take one element from
> each nested list
>
> i.e
> [2, 4, 6, ..., ...]
> [2, 4, 2, ..., ...]
You've seen many interesting approaches to this. Cool! Here's one for
brevity, but relying on 2.2:
from __future__ import generators
from test.test_generators import conjoin
alist = [[2, 3, 4, 5],
[4, 5, 6, 7, 34],
[6, 2, 7, 4]]
count = 0
for one in conjoin(map(lambda x: lambda: iter(x), alist)):
count += 1
if count < 6 or count > 75:
print "%2d: %s" % (count, one)
elif count == 6:
print "..."
That prints:
1: [2, 4, 6]
2: [2, 4, 2]
3: [2, 4, 7]
4: [2, 4, 4]
5: [2, 5, 6]
...
76: [5, 7, 4]
77: [5, 34, 6]
78: [5, 34, 2]
79: [5, 34, 7]
80: [5, 34, 4]
The "conjoin" imported there is a simple but general backtracking schema,
named in honor of Icon's "conjunction" operator. It marches over all
cross-products of a list of no-argument functions that return iterators
(think that real fast 10 times <wink>), and generating a full cross-product
is the simplest thing you can do with it. test_generators.py builds some
fancier things on top of it, and has 3 distinct implementations of conjoin()
(from purely recursive to purely iterative).
Since the implementation is generator-based, you don't have to compute all
the results at once:
>>> get = conjoin(map(lambda x: lambda: iter(x), alist)).next
>>> get()
[2, 4, 6]
>>> get()
[2, 4, 2]
>>> get()
[2, 4, 7]
>>> get()
[2, 4, 4]
>>> get()
[2, 5, 6]
>>>
Note that since "get" is also an iterator, nothing to stop you from feeding
it back into conjoin, either! The disgusting possibilities are left to
sicker imaginations than mine.
cute-but-not-mandatory-ly y'rs - tim
More information about the Python-list
mailing list