列表到字典的转换,每个键有多个值?
- 2025-02-21 08:50:00
- admin 原创
- 72
问题描述:
我有一个包含键/值对的 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
是一个临时的 defaultdict,其值是列表,将在最后一行转换为元组。这样,您就可以将其附加到列表中,而不是在主循环中重新创建元组。
解决方案 2:
使用列表而不是元组作为字典值:
l = [[1, 'A'], [1, 'B'], [2, 'C']]
d = {}
for key, val in l:
d.setdefault(key, []).append(val)
print(d)
与使用 相比,使用普通字典通常更可取defaultdict
,特别是如果您只构建一次然后在代码中继续从中读取:
首先,普通词典的构建和访问速度更快。
其次,更重要的是,如果您尝试访问不存在的键,而不是默默地创建该键,则后续的读取操作将出错。普通字典允许您明确说明何时要创建键值对,而defaultdict
对于任何类型的访问,字典始终会隐式地创建它们。
解决方案 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 中仍有效。
解决方案 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',)}
解决方案 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 是有保证的。我的代码应该可以工作,即使temp['IP_addr'].to_list() == []
{'fooboo_NaN': ['1.1.1.1', '8.8.8.8']}
解决方案 7:
我将把两个硬币投入到这个精彩的讨论中)我试图想出一个只有标准库的一行解决方案。请原谅我导入了两个多余的代码。也许下面的代码可以以令人满意的质量解决问题(对于 python3):
from functools import reduce
from collections import defaultdict
a = [1, 1, 2, 3, 1]
b = ['A', 'B', 'C', 'D', 'E']
c = zip(a, b)
print({**reduce(lambda d,e: d[e[0]].append(e[1]) or d, c, defaultdict(list))})
扫码咨询,免费领取项目管理大礼包!