Python按键拉链

时间:2015-04-15 08:35:34

标签: python list

我想组合(zip?)两个python的元组列表,但是匹配一个键。

e.g。我想创建一个带有两个输入列表并生成如下输出的函数:

lst1 = [(0, 1.1), (1, 1.2), (2, 1.3),           (5, 2.5)]
lst2 = [          (1, 4.5), (2, 3.4), (4, 2.3), (5, 3.2)]

desiredOutput = [(1, 1.2, 4.5), (2, 1.3, 3.4), (5, 2.5, 3.2)]

我可以非常混乱并且手动使用循环,但我认为必须有一些itertools /压缩函数,这将大大简化这一点。

我确定答案已经存在并且显而易见,我只是没有正确的语言来搜索它。

==

((对于它的价值,这是我天真的解决方案。我希望找到更整洁/更pythonic的东西:

def key_zipper(lst1, lst2):    
    dict1 = dict(lst1)
    dict2 = dict(lst2)

    intersectKeys = [k for k in dict1.keys() if k in dict2.keys()]

    output = []

    for key in intersectKeys:
        output.append((key, dict1[key], dict2[key]))

    return output

谢谢))

4 个答案:

答案 0 :(得分:11)

>>> [(i, a, b) for i, a in lst1 for j, b in lst2 if i==j]
[(1, 1.2, 4.5), (2, 1.3, 3.4), (5, 2.5, 3.2)]

答案 1 :(得分:4)

仍然有点混乱,但有效:

def combine(lst1, lst2):
  d2 = dict(lst2)
  return [(k, v, d2[k]) for (k, v) in lst1 if k in d2]

<强>更新

如果我在生产代码中实际使用它,我会稍微重构一下:

def dict_intersection(d1, d2):
    return [(k,v,d2[k]) for (k,v) in d1.items() if k in d2]

然后在你的情况下,我打电话

lst1 = [(0, 1.1), (1, 1.2), (2, 1.3), (5, 2.5)]
lst2 = [(1, 4.5), (2, 3.4), (4, 2.3), (5, 3.2)]
common = dict_intersection(dict(lst1), dict(lst2))

@Vincent的回答也很好。

答案 2 :(得分:2)

将第二个列表转换为字典,然后您可以检查密钥是否存在而不迭代整个第二个列表:

def func(lst1,lst2):
    d2 = dict(lst2)
    return [(k,a,d2[k]) for (k,a) in lst1 if d2.has_key(k) ]

答案 3 :(得分:2)

使用itertools.groupbyheapq.merge的解决方案:

from itertools import groupby
from heapq import merge
from operator import itemgetter

def key_zipper(*lst):
    for k, v in groupby(merge(*lst), itemgetter(0)):
        yield (k,) + tuple(map(itemgetter(1), v))

lst1 = [(0, 1.1), (1, 1.2), (2, 1.3),           (5, 2.5)]
lst2 = [          (1, 4.5), (2, 3.4), (4, 2.3), (5, 3.2)]
print(list(key_zipper(lst1, lst2)))
# [(0, 1.1), (1, 1.2, 4.5), (2, 1.3, 3.4), (4, 2.3), (5, 2.5, 3.2)]

mergegroupby都需要对其输入进行排序。如果列表并不总是排序,那么您需要确保这样做:

def key_zipper(*lst):
    for k, v in groupby(merge(*map(sorted, lst)), itemgetter(0)):
        yield (k,) + tuple(map(itemgetter(1), v))

这样做的好处是它可以使用任意数量的输入列表,并且对于大型列表具有更好的运行时间。

请注意,这里我把它写成一个生成元组的生成器而不是返回元组列表的函数,但将其转换为列表是微不足道的。