【问题标题】:All possible merges of lists in pythonpython中所有可能的列表合并
【发布时间】:2015-11-19 18:17:23
【问题描述】:

我想获得在 python 中合并 2 个(或理想情况下为 n 个)列表的所有可能方法,同时保持每个列表的内部顺序 - 即我想找到一些行为如下的函数 all_merges:

a = all_merges([1,2],[3,4]) 

结果:

a = [
[1,2,3,4],
[1,3,2,4],
[1,3,4,2],
[3,1,2,4],
[3,1,4,2],
[3,4,1,2]   ]

(我希望这是全部)

我找不到简单的“pythonic”方式来做到这一点 - 请帮助!

=====

注意:

我正在考虑这样的事情(写成相对可读):

from itertools import permutations
def all_merges(list1,list2):
    a = [1]*len(list1)
    b = [2]*len(list2)
    indexes = list(set(list(permutations(a+b))))
    lists = [[]]*3
    res = indexes # just for readability, will be overwriting indexes as we go along
    for perm in indexes:
        lists[1] = copy(list1)
        lists[2] = copy(list2)
        merge = perm
        for i in range(0,len(perm)):
            merge[j] = lists[perm[i]].pop(0)
    return res

然而在舞台上

list(set(list(permutations(a+b))

如果列表的总长度高达 15,我会从

获得大量结果
permutations(a+b)

(准确地说是 15 个!),而我最多只有 15choose7 (= 6435) 个不同的合并。

我意识到这里提供了对该行的替换,作为函数:permutations with unique values 但是现在这变得很混乱,我想看看是否有更清洁的解决方案来解决我原来的问题。

【问题讨论】:

    标签: python list merge permutation


    【解决方案1】:

    每个可能的合并直接对应于(len(a) + len(b)) choose len(a) 方法之一,为最终列表中的a 的元素选择len(a) 位置:

    import itertools
    def all_merges(a, b):
        # object guaranteed not to be in either input list
        sentinel = object()
        merged_length = len(a) + len(b)
        for a_positions in itertools.combinations(xrange(merged_length), len(a)):
            merged = [sentinel] * merged_length
    
            # Place the elements of a in their chosen positions.
            for pos, a_elem in zip(a_positions, a):
                merged[pos] = a_elem
    
            # Place the elements of b in the positions not taken.
            b_iter = iter(b)
            for pos in xrange(merged_length):
                if merged[pos] is sentinel:
                    merged[pos] = next(b_iter)
    
            yield merged
    

    这可以通过多种方式扩展到更多列表,例如通过使用某种技术(可能是Algorithm L)通过所有方式为列表元素分配位置,或者通过重复应用 2-way 合并。

    【讨论】:

    • 这太好了,谢谢!对于后代,我会注意到我必须将 xrange 更改为 range,并且我使用 list(all_merges(a,b)) 得到了想要的结果
    猜你喜欢
    • 1970-01-01
    • 2023-02-14
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多