在Python中嵌套列表(列表中的列表)中元素的所有无序/混洗的唯一排列?

时间:2017-08-04 02:34:30

标签: python algorithm graph combinatorics itertools

我有两级嵌套列表,如下所示。

[[0, 1], [2], [3, 4], [5, 5], [6], [7], [8], [9], [10, 11], [12]]

我希望生成此嵌套列表的所有8个唯一排列,但我的应用程序绝对需要输出(伪)随机和无序。通常,排列策略按顺序产生排列,但我希望能够不按顺序产生所有排列。

此外,这个MUST可以通过某个生成器完成,因为嵌套列表可能非常长,并且唯一排列的数量可以组合爆炸。

例如,以上列表需要以下输出。

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

...而不是由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)

即使是一些与itertools.product完全相同的解决方案,但是无序生成排列也会对我有所帮助。任何帮助表示赞赏。

以下代码说明了我现有的方法。

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
    print
    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
    print len(set_l)
    print
    # for s in set_l:
    #     print s

3 个答案:

答案 0 :(得分:1)

您可以尝试迭代以下生成器:

def random_perm(l):
    while True:
        yield [random.choice(sublist) for sublist in l]

样本用法:

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

输出:

[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]

然而,正如其他人在评论中指出的那样,除非你以某种方式将收益结果缓存在内存中,否则你无法保证你不会获得重复。您也无法保证在任何8次连续迭代中获得所有8次独特迭代。

答案 1 :(得分:0)

如果内存不是问题,您可以尝试以下方法:

permList = itertools.product(*list_of_lists)
randomPermList = numpy.random.permutation(list(permList))

这是唯一且随机的,但不会是迭代。

答案 2 :(得分:0)

比你目前的解决方案更清洁一点:

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
print
set_l = set()
for _ in xrange(iter_count*100):
    choices = tuple([np.random.choice(sub_seq) for sub_seq in meta_seq])
    if not choices in set_l:
        set_l.add(choices)
        print choices
print
print len(set_l)
print