关于字典:Python相当于字典的zip

Python equivalent of zip for dictionaries

如果我有这两个列表:

1
2
la = [1, 2, 3]
lb = [4, 5, 6]

我可以对它们进行如下迭代:

1
2
for i in range(min(len(la), len(lb))):
    print la[i], lb[i]

或更大程度上的脓肿

1
2
for a, b in zip(la, lb):
    print a, b

如果我有两本字典呢?

1
2
da = {'a': 1, 'b': 2, 'c': 3}
db = {'a': 4, 'b': 5, 'c': 6}

同样,我可以手动迭代:

1
2
for key in set(da.keys()) & set(db.keys()):
    print key, da[key], db[key]

是否有一些内置方法允许我如下迭代?

1
2
for key, value_a, value_b in common_entries(da, db):
    print key, value_a, value_b


没有内置函数或方法可以做到这一点。但是,您可以很容易地定义自己的。

1
2
3
def common_entries(*dcts):
    for i in set(dcts[0]).intersection(*dcts[1:]):
        yield (i,) + tuple(d[i] for d in dcts)

这建立在您提供的"手动方法"的基础上,但是,与zip一样,可以用于任何数量的字典。

1
2
3
4
>>> da = {'a': 1, 'b': 2, 'c': 3}
>>> db = {'a': 4, 'b': 5, 'c': 6}
>>> list(common_entries(da, db))
[('c', 3, 6), ('b', 2, 5), ('a', 1, 4)]

当只提供一个字典作为参数时,它实质上返回dct.items()

1
2
>>> list(common_entries(da))
[('c', 3), ('b', 2), ('a', 1)]


您可能需要使用python集类型进行交集。

1
2
3
4
5
6
7
da = {'a': 1, 'b': 2, 'c': 3, 'e': 7}
db = {'a': 4, 'b': 5, 'c': 6, 'd': 9}

dc = set(da) & set(db)

for i in dc:
  print i,da[i],db[i]

干杯,

K


字典键视图的设置与Python3中的设置类似。可以删除set()

1
2
for key in da.keys() & db.keys():
    print(key, da[key], db[key])

在python 2中:

1
2
for key in da.viewkeys() & db.viewkeys():
    print key, da[key], db[key]


如果有人在寻找广义解:

1
2
3
4
5
6
7
8
9
import operator
from functools import reduce


def zip_mappings(*mappings):
    keys_sets = map(set, mappings)
    common_keys = reduce(set.intersection, keys_sets)
    for key in common_keys:
        yield (key,) + tuple(map(operator.itemgetter(key), mappings))

或者,如果要将键与值分开并使用类似的语法

1
2
for key, (values, ...) in zip_mappings(...):
    ...

我们可以用替换最后一行

1
yield key, tuple(map(operator.itemgetter(key), mappings))

。测验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from collections import Counter


counter = Counter('abra')
other_counter = Counter('kadabra')
last_counter = Counter('abbreviation')
for (character,
     frequency, other_frequency, last_frequency) in zip_mappings(counter,
                                                                 other_counter,
                                                                 last_counter):
    print('character"{}" has next frequencies: {}, {}, {}'
          .format(character,
                  frequency,
                  other_frequency,
                  last_frequency))

给我们

1
2
3
character"a" has next frequencies: 2, 3, 2
character"r" has next frequencies: 1, 1, 1
character"b" has next frequencies: 1, 1, 2

(在Python 2.7.12Python 3.5.2上测试)