I have two-level nested list like following.
[[0, 1], [2], [3, 4], [5, 5], [6], [7], [8], [9], [10, 11], [12]]
I want to generate all 8 unique permutations of this nested list, but my application absolutely needs the output to be (pseudo-)randomized and unordered. Usually, permutation strategies produce the permutations in order, but I want to be able to produce all permutations out of order.
Moreover, this MUST be done through some generator, as the nested list can be very long, and number of unique permutations can explode combinatorially.
Case in point, the following output is desired for the above list.
(0, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(0, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 10, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 11, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 11, 12)
...as opposed to the following, which is generated by itertools.product(*some_list):
(0, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(0, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(0, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(0, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 11, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 10, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 11, 12)
(0, 2, 4, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 3, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 10, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 11, 12)
(1, 2, 4, 5, 6, 7, 8, 9, 10, 12)
Even some solution that does exactly what itertools.product does, but generates permutations out of order will help me a lot. Any help is appreciated.
The following code illustrates my existing approach.
def perm_attempt():
meta_seq = [[0, 1], [2], [3, 4], [5, 5], [6], [7], [8], [9], [10, 11], [12]]
print meta_seq
iter_count = np.prod([len(set(x)) for x in meta_seq])
print iter_count
set_l = set()
for _ in xrange(iter_count*10):
l = [np.random.choice(x) for x in meta_seq]
# print l
set_l.add(tuple(l))
print len(set_l)
# for s in set_l:
# print s
解决方案
You can try iterating over the following generator:
def random_perm(l):
while True:
yield [random.choice(sublist) for sublist in l]
Sample usage:
l = [[0, 1], [2], [3, 4], [5, 5], [6], [7], [8], [9], [10, 11], [12]]
g = random_perm(l)
for _ in range(10):
print(next(g))
Output:
[0, 2, 4, 5, 6, 7, 8, 9, 10, 12]
[1, 2, 4, 5, 6, 7, 8, 9, 11, 12]
[0, 2, 3, 5, 6, 7, 8, 9, 10, 12]
[0, 2, 3, 5, 6, 7, 8, 9, 10, 12]
[0, 2, 3, 5, 6, 7, 8, 9, 11, 12]
[1, 2, 4, 5, 6, 7, 8, 9, 10, 12]
[0, 2, 3, 5, 6, 7, 8, 9, 11, 12]
[1, 2, 4, 5, 6, 7, 8, 9, 11, 12]
[1, 2, 4, 5, 6, 7, 8, 9, 10, 12]
[0, 2, 4, 5, 6, 7, 8, 9, 10, 12]
However, as others have pointed out in the comments, unless you cache the yield results in memory somehow, you can't really guarantee you won't get duplicates. You are also not guaranteed to get all 8 unique iterations in any 8 consecutive iterations.