每个键有多个值的列表到字典转换?

Posted

技术标签:

【中文标题】每个键有多个值的列表到字典转换?【英文标题】:list to dictionary conversion with multiple values per key? 【发布时间】:2011-07-19 16:36:26 【问题描述】:

我有一个包含键/值对的 Python 列表:

l = [[1, 'A'], [1, 'B'], [2, 'C']]

我想将列表转换为字典,其中每个键的多个值将聚合成一个元组:

1: ('A', 'B'), 2: ('C',)

迭代解法很简单:

l = [[1, 'A'], [1, 'B'], [2, 'C']]
d = 
for pair in l:
    if pair[0] in d:
        d[pair[0]] = d[pair[0]] + tuple(pair[1])
    else:
        d[pair[0]] = tuple(pair[1])

print(d)

1: ('A', 'B'), 2: ('C',)

对于这项任务,是否有更优雅的 Pythonic 解决方案?

【问题讨论】:

【参考方案1】:
from collections import defaultdict

d1 = defaultdict(list)

for k, v in l:
    d1[k].append(v)

d = dict((k, tuple(v)) for k, v in d1.items())

d 现在包含 1: ('A', 'B'), 2: ('C',)

d1 是一个以列表为值的临时默认字典,将在最后一行转换为元组。这样,您将追加到列表,而不是在主循环中重新创建元组。

【讨论】:

【参考方案2】:

使用列表而不是元组作为字典值:

l = [[1, 'A'], [1, 'B'], [2, 'C']]
d = 
for key, val in l:
    d.setdefault(key, []).append(val)

print(d)

使用普通字典通常比 defaultdict 更可取,特别是如果您只构建一次,然后在以后的代码中继续读取它:

首先,普通字典的构建和访问速度更快。

其次,更重要的是,如果您尝试访问一个不存在的密钥,而不是静默创建该密钥,那么后面的读取操作将出错。普通字典可让您明确说明何时要创建键值对,而 defaultdict 始终在任何类型的访问中隐式创建它们。

【讨论】:

使用d.setdefault(key,[]).append(val)d.get(key,[]).append(val)有什么区别/优势? setdefault() 的优点是使用 .get() 不起作用:\ @jtlz2 .get() 仅从字典中检索值。如果给定键没有条目,get 将愉快地返回新列表并允许将值附加到该列表,但不会更新字典以实际包含新列表,因此新列表将在之后被垃圾回收追加新值。【参考方案3】:

这种方法比较高效,也比较紧凑:

reduce(lambda x, (k,v): x[k].append(v) or x, l, defaultdict(list))

在 Python3 中,这变为(明确导出):

dict(functools.reduce(lambda x, d: x[d[0]].append(d[1]) or x, l, collections.defaultdict(list)))

请注意,reduce 已移至 functools,并且 lambda 不再接受元组。此版本在 2.6 和 2.7 中仍然有效。

【讨论】:

不错,但在 python 3.5 或更高版本中无效【参考方案4】:

输入列表中的键是否已经排序?如果是这种情况,您就有了一个实用的解决方案:

import itertools

lst = [(1, 'A'), (1, 'B'), (2, 'C')]
dct = dict((key, tuple(v for (k, v) in pairs)) 
           for (key, pairs) in itertools.groupby(lst, lambda pair: pair[0]))
print dct
# 1: ('A', 'B'), 2: ('C',)

【讨论】:

如果你import operator,你可以写itertools.groupby(sorted(lst), operator.itemgetter(0))【参考方案5】:

我创建了一个值列表,如下所示:

performance_data = driver.execute_script('return window.performance.getEntries()')  

然后我必须将数据(名称和持续时间)存储在具有多个值的字典中:

dictionary = 
    for performance_data in range(3):
        driver.get(self.base_url)
        performance_data = driver.execute_script('return window.performance.getEntries()')
        for result in performance_data:
            key=result['name']
            val=result['duration']
            dictionary.setdefault(key, []).append(val)
        print(dictionary)

【讨论】:

【参考方案6】:

我的数据在 Pandas.DataFrame 中

myDict = dict()

for idin set(data['id'].values):
    temp = data[data['id'] == id]
    myDict[id] = temp['IP_addr'].to_list()
    
myDict

给我一​​个包含键、ID、映射到 >= 1 IP_addr 的字典。第一个 IP_addr 是 Guaranteed。即使temp['IP_addr'].to_list() == []

,我的代码也应该可以工作
'fooboo_NaN': ['1.1.1.1', '8.8.8.8']

【讨论】:

以上是关于每个键有多个值的列表到字典转换?的主要内容,如果未能解决你的问题,请参考以下文章

Python将列表转换为具有多个键值的字典[关闭]

多值字典?

将数据框转换为具有多个值的字典

python pandas将数据框转换为具有多个值的字典

django-QueryDict 对象

如何比较字典值中的多个数组,并将每个数组元素的字典键映射到新数组/列表中