我有一个类似的字典:
{'x': [1, 2, 3], 'y': [4, 5, 6]}
我想将其转换为以下格式:
[{'x': 1, 'y': 4}, {'x': 2, 'y': 5}, {'x': 3, 'y': 6}]
我可以通过显式循环来实现它,但有一种很好的pythonic方法吗?
编辑:原来有一个类似的问题here,其中一个answers与此处接受的答案相同,但该答案的作者写道“我不容忍使用此类代码在任何一种真实的系统中“。有人可以解释为什么这样的代码是坏的?它看起来非常优雅。
答案 0 :(得分:11)
使用zip()
几次,指望直到dict.items()
上的dict
和迭代都以相同的顺序返回元素,只要字典没有在其间发生变异:
[dict(zip(d, col)) for col in zip(*d.values())]
zip(*d.values())
来电transposes the list values和zip(d, col)
来电再次将每列与字典中的键配对。
以上相当于手动拼写密钥:
[dict(zip(('x', 'y'), col)) for col in zip(d['x'], d['y'])]
无需手动拼出密钥。
演示:
>>> d = {'x': [1, 2, 3], 'y': [4, 5, 6]}
>>> [dict(zip(d, col)) for col in zip(*d.values())]
[{'x': 1, 'y': 4}, {'x': 2, 'y': 5}, {'x': 3, 'y': 6}]
答案 1 :(得分:2)
我认为没有任何易于阅读,简洁的1-liner(尽管它可能不难想出难点< / em>阅读,精简1-liner ...;) - 至少不是一般情况下(任意数量的dict项目,其中密钥未知)。
如果您知道 dict的键,我认为它可能最容易使用(特别是因为示例中只有2个)。
在2遍中构建新的dicts。第一遍填写x
,第二遍填写y
。
new_dicts = [{'x': x} for x in d['x']]
for new_dict, y in zip(new_dicts, d['y']):
new_dict['y'] = y
如果你宁愿一次通过,我认为这也不错:
new_dicts = [{'x': x, 'y': y} for x, y in zip(d['x'], d['y'])]
如果你有一个按键列表,我可能会略有不同......
import operator
value_getter = operator.itemgetter(*list_of_keys)
new_dicts_values = zip(*value_getter(d))
new_dicts = [
dict(zip(list_of_keys, new_dict_values))
for new_dict_values in new_dicts_values]
这与Martijn的回答几乎相同......不过,我认为将其分解并给出一些名称有助于让它更清楚一些正在发生的事情。此外,这消除了必须说服自己用无序的列值列表来压缩无序dict
是正常的心理开销,因为它们以相同的方式无序排序......
当然,如果你实际上没有钥匙列表,你可以随时获得一个
list_of_keys = list(d)
答案 2 :(得分:1)
如果
d = {'x': [1, 2, 3], 'y': [4, 5, 6]}
可以尝试:
keys = d.keys()
print map(lambda tupl: map(lambda k,v: {k:v}, keys, tupl), zip(*d.itervalues()))
看起来像pythonic但是对于较大的条目,每次map调用lambda函数时lambda调用的开销都会增加。