【问题标题】:Merging Two Outer Lists Based on Iterated Inner List Value基于迭代的内部列表值合并两个外部列表
【发布时间】:2011-09-19 20:53:55
【问题描述】:

我有两个列表 - 即

[['1', 'expired', 'test', '0'], ['31', 'active', 'test', '1']]

还有

[['1', 'Andrew', 'Alexander'], ['31', 'John', 'Smith']]

我们称他们为list1list2

我想合并 list1list2,但仅限于(注意,这是伪代码,试图弄清楚如何在 Python 中编程)

x[0] in list1 == x[0] in list2

我不知道怎么写出来。

我的意思是合并(伪代码)

list[x] = list1[x] + list2[x] while x[0] in list1 == x[0] in list2

所需的输出:

[['1', 'expired', 'test', '0', '1', 'Andrew', 'Alexander'], ['31', 'active', 'test', '1', '31', 'John', 'Smith']]

唯一的关键点是并非所有的 x[0] 都会完美匹配。

【问题讨论】:

  • 这里的“合并”到底是什么意思?期望的输出是什么?
  • 请准确给出您希望示例输出的内容——我还不是很清楚。
  • 仍在尝试找出适合我的正确答案。我的很多未选择的答案都是这样的。过去我也一直试图给问题打勾。我正在努力成为社区的好成员!

标签: python list iteration


【解决方案1】:

使用 agf 使用 collections.defaultdict 的想法,这在 O(m+n) 中,其中 mn 是列表的长度。

import collections
import itertools

x=[['1', 'expired', 'test', '0'], ['31', 'active', 'test', '1']]
y=[['1', 'Andrew', 'Alexander'], ['31', 'John', 'Smith']]

result=collections.defaultdict(list)
for item in itertools.chain(x,y):
    result[item[0]].append(item)
result=[list(itertools.chain.from_iterable(value)) for value in result.values()]
print(result)

产量

[['1', 'expired', 'test', '0', '1', 'Andrew', 'Alexander'], ['31', 'active', 'test', '1', '31', 'John', 'Smith']]

在 cmets 中,OP 说所需的输出是

[['1', 'expired', 'test', '0', 'Andrew', 'Alexander'], ['31', 'active', 'test', '1', 'John', 'Smith']]

(这与原始问题中发布的所需输出不同。)

然后:

import collections
import itertools

x=[['1', 'expired', 'test', '0'], ['31', 'active', 'test', '1']]
y=[['1', 'Andrew', 'Alexander'], ['31', 'John', 'Smith']]

result={}
for item in itertools.chain(x,y):
    result.setdefault(item[0],item[:1]).extend(item[1:])
result=result.values()
print(result)

这是我发现使用setdefaultcollections.defaultdict 更方便的少数几次之一。

【讨论】:

    【解决方案2】:

    如果你想将[[1, 'a'], [2, 'b']][[1, 'c'], [3, 'd']] 合并到[[1, 'a', 'c'], [2, 'b'], [3, 'd']]

    from collections import defaultdict
    dict1_2 = defaultdict(list)
    dict1_2.update((item[0], item[1:]) for item in list1)
    for item in list2:
        dict1_2[item[0]].append(item[1:])
    

    如果你想让它们合并到[[1, 'a', 'c']]:

    dict1 = dict((item[0], item[1:]) for item in list1)
    dict1_2 = {}
    for item in list2:
        key = item[0]
        if key in dict1:
            dict1_2[key] = dict1[key] + item[1:]
    

    您使用item[0] 作为键,因此您应该使用适合它的数据类型。在这种情况下,这是一个字典/映射。

    这(平均而言)在线性时间内起作用,O(m+n)(其中 m 和 n 是列表的长度)。任何使用嵌套循环或类似的解决方案都将是 O(m*n)

    如果您确实需要将数据作为列表返回,您可以这样做

    list1_2 = [[key] + value for key, value in dict1_2.iteritems()]
    

    【讨论】:

    • 它们并不完全相同。其他列表中有一些不同/不存在。这就是为什么我在 Python 中这样做,而不是说,只是在 Excel 中将两个列表合并在一起。
    • 话虽如此,我想要 [['1', 'expired', 'test', '0', 'Andrew', 'Alexander'], ['31', 'active', “测试”、“1”、“约翰”、“史密斯”]]
    • @Andrew 重新编辑。根据您想要对仅一个列表中的项目执行的操作,我提供了两个版本。
    【解决方案3】:
    resultlist = []
    for x in list1:
        for y in list2:
            if x[0] == y[0]:
                resultlist.append(x+y)
    

    【讨论】:

    • OP 说只有当两个列表中的第一个元素相同时才应该添加项目 - 还是我弄错了?
    • 这是 O(len(list1)*len(list2)) 时间,可以在线性平均时间内完成。
    【解决方案4】:

    不是最好的方法,但绝对简洁且难以阅读,如果你想要的话:

    >>> l1 = [['1', 'expired', 'test', '0'], ['31', 'active', 'test', '1']]
    >>> l2 = [['1', 'Andrew', 'Alexander'], ['31', 'John', 'Smith']]
    
    >>> [sl1 + list(*[sl2[1:] for sl2 in l2 if sl2[0]==sl1[0]]) for sl1 in l1]
    
    [['1', 'expired', 'test', '0', 'Andrew', 'Alexander'], ['31', 'active', 'test', '1', 'John', 'Smith']]
    

    请不要在任何实际代码中实际使用它。

    【讨论】:

    • 你想要next((sl2[1:] for sl2 in l2 if sl2[0]==sl1[0]), []),而不是你想出的那个疯狂的清单:)。此外,这将添加仅存在于 list1 中的项目,而不是仅存在于 list2 中的项目——我不知道他是否希望添加它们,但我确定他不希望它不对称.
    【解决方案5】:
    l1 = [['1', 'expired', 'test', '0'], ['31', 'active', 'test', '1']]
    l2 = [['1', 'Andrew', 'Alexander'], ['31', 'John', 'Smith'], ['51', 'Johnny', 'Nomatch']]
    
    from itertools import groupby, chain
    from operator import itemgetter
    
    all = sorted(chain(l1,l2), key=itemgetter(0)) # puts the related lists together
    groups = groupby(all, itemgetter(0)) # groups them by first element
    chains = (group for key, group in groups) # get each group
    print [list(chain.from_iterable(g)) for g in chains] # merge them
    

    这是一个单线;-)

    包含不匹配的项目。你可以通过简单地检查len(group) > 4来过滤掉它们。

    【讨论】:

      猜你喜欢
      • 2021-06-26
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 2018-03-15
      • 2011-12-20
      • 2011-01-31
      • 1970-01-01
      • 2021-11-27
      相关资源
      最近更新 更多