【问题标题】:Merge python lists of different lengths合并不同长度的python列表
【发布时间】:2017-12-04 21:47:16
【问题描述】:

我正在尝试合并两个 python 列表,它们在给定索引处的值将在新列表中形成一个列表(元素)。例如:

merge_lists([1,2,3,4], [1,5]) = [[1,1], [2,5], [3], [4]]

我可以迭代这个函数来组合更多的列表。实现此目的最有效的方法是什么?

编辑(第 2 部分)

在测试我之前选择的答案后,我意识到我有额外的标准和一个更普遍的问题。我还想合并包含列表 值的列表。例如:

merge_lists([[1,2],[1]] , [3,4]) = [[1,2,3], [1,4]]

目前提供的答案在这种情况下会生成更高维度的列表。

【问题讨论】:

  • 我已经更新了问题描述 - 意识到我不需要集合,只需列出 :)

标签: python python-2.7 list merge list-comprehension


【解决方案1】:

一种选择是使用itertools.zip_longest(在python 3中):

from itertools import zip_longest    

[[x for x in t if x is not None] for t in zip_longest([1,2,3,4], [1,5])]
# [[1, 1], [2, 5], [3], [4]]

如果您更喜欢套装:

[{x for x in t if x is not None} for t in zip_longest([1,2,3,4], [1,5])]
# [{1}, {2, 5}, {3}, {4}]

在 python 2 中,使用itertools.izip_longest:

from itertools import izip_longest    

[[x for x in t if x is not None] for t in izip_longest([1,2,3,4], [1,5])]
#[[1, 1], [2, 5], [3], [4]]

更新以处理稍微复杂的情况:

def flatten(lst):

    result = []
    for s in lst:
        if isinstance(s, list):
            result.extend(s)
        else:
            result.append(s)

    return result

这很好地处理了上述两种情况:

[flatten(x for x in t if x is not None) for t in izip_longest([1,2,3,4], [1,5])]
# [[1, 1], [2, 5], [3], [4]]

[flatten(x for x in t if x is not None) for t in izip_longest([[1,2],[1]] , [3,4])]
# [[1, 2, 3], [1, 4]]

请注意,尽管这适用于上述两种情况,但它仍然可以在更深的嵌套结构下中断,因为这种情况会很快变得复杂。更通用的解决方案可以看here

【讨论】:

  • if x 过于宽泛,例如0 会被删除吗?也许是针对None 的显式测试?
  • 另外,OP 将其标记为 Python 2.7,所以它应该是 izip_longestzip_longest 是 Python 3.x
  • 这个答案真是太棒了!我只是把它扔到一个函数中,比如:def merge_lists(a, b): return [[x for x in t if x is not None] for t in izip_longest(a, b)]。谢谢!!
  • 我更新了描述一个更普遍的问题 - 这个解决方案可以轻松修改吗?
【解决方案2】:

使用zip() 获得所需输出的另一种方法:

 def merge(a, b):
     m = min(len(a), len(b))
     sub = []
     for k,v in zip(a,b):
         sub.append([k, v])
     return sub + list([k] for k in a[m:]) if len(a) > len(b) else sub + list([k] for k in b[m:])

a = [1, 2, 3, 4]
b = [1, 5]
print(merge(a, b))
>>> [[1, 1], [2, 5], [3], [4]]

【讨论】:

    【解决方案3】:

    您可以使用itertools.izip_longestfilter()

    >>> lst1, lst2 = [1, 2, 3, 4], [1, 5]
    >>> from itertools import izip_longest
    >>> [list(filter(None, x)) for x in izip_longest(lst1, lst2)]
    [[1, 1], [2, 5], [3], [4]]
    

    工作原理:izip_longest() 聚合两个列表中的元素,用Nones 填充缺失值,然后用filter() 过滤掉。

    【讨论】:

    • izip_longest 在 Python 3 中不存在
    • 问题被标记为python-2.7。在 python 3 中使用 zip_longest.
    【解决方案4】:

    另一种使用 zip_longest 和来自 itertools 的链的方式:

    import itertools
    [i for i in list(itertools.chain(*itertools.zip_longest(list1, list2, list3))) if i is not None]
    

    或 2 行(更易读):

    merged_list = list(itertools.chain(*itertools.zip_longest(a, b, c)))
    merged_list = [i for i in merged_list if i is not None]
    

    【讨论】:

      猜你喜欢
      • 2020-06-27
      • 2017-11-30
      • 1970-01-01
      • 2020-04-10
      • 2019-12-21
      • 2019-10-16
      • 2017-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多