【问题标题】:Transposing (pivoting) a dict of lists in python [duplicate]在python中转置(旋转)列表的字典[重复]
【发布时间】:2016-09-26 03:12:37
【问题描述】:

我有一本看起来像这样的字典:

{'x': [1, 2, 3], 'y': [4, 5, 6]}

我想把它转换成如下格式:

[{'x': 1, 'y': 4}, {'x': 2, 'y': 5}, {'x': 3, 'y': 6}] 

我可以通过显式循环来做到这一点,但有没有一种好的 Python 方式来做到这一点?

编辑:原来有一个类似的问题here,其中一个answers 与此处接受的答案相同,但该答案的作者写道:“我不容忍在任何类型的真实系统”。有人可以解释为什么这样的代码不好吗?在我看来它非常优雅。

【问题讨论】:

  • 知道字典中的键吗?还是您想要一个不假定已知密钥的解决方案?在这种情况下,我认为具有已知键的解决方案最终可能会更容易阅读(但显然不太通用)。
  • @mgilson:是的,我知道钥匙
  • @mgilson:我应该更清楚。我知道键,因为我有一个它们的列表,但它们可以增长,因为可能有 'x', 'y', 'z' 作为键。我有一个列表,尽管说l = [ 'x', 'y', 'z' ]
  • @Bilentor 正如您在编辑中所承认的那样,这是重复的。如果您有其他问题,那么您应该将其作为一个单独的问题提出,而不是作为次要问题。

标签: python dictionary nested pivot transpose


【解决方案1】:

使用zip() 几次,指望dict.items() 和直接在dict 上的迭代都以相同的顺序返回元素,只要字典在两者之间没有突变:

[dict(zip(d, col)) for col in zip(*d.values())]

zip(*d.values()) 调用 transposes the list valueszip(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 到 10 分钟的时间来弄清楚它在做什么......
  • 我会说这很好而且很一般......我考虑得越多(鉴于 OP 在原始 dict 中不仅有 2 个键),我'我不确定是否有更好的方法来做到这一点...有时您必须将一般的,有些难以阅读的东西放在代码中,然后评论它的作用,以便您未来的自己可以弄清楚...
【解决方案2】:

我不认为有任何易读,简洁的 1-liner (虽然可能不难想出一个难读,简洁的 1-liner ... ;) -- 至少在一般情况下不是(任意数量的 dict 项,其中键未知)。

如果您知道 dict 的键,我认为使用它可能最容易(特别是因为示例中只有 2 个)。

在 2 遍中构建新的字典。第一遍填写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)

【讨论】:

  • 我应该更清楚。我知道键,因为我有一个它们的列表,但它们可以增长,因为可能有 'x', 'y', 'z' 作为键。我有一个列表,尽管说l = [ 'x', 'y', 'z' ]
【解决方案3】:

如果

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()))

看起来像 Python,但对于较大的条目,每次 map 调用 lambda 函数时 lambda 调用的开销会增加。

【讨论】:

  • FWIW,对我来说它看起来不像 pythonic ......我认为有些人认为“pythonic”意味着你设法将整个东西放在一条线上。实际上,“pythonic”意味着使用常见的 python 习语尽可能简单地完成任务。
  • 如果您想使用map/lambda,我认为map(lambda *vals: dict(zip(d, vals)), *d.values()) 更好,但仍然受到与Martijn 相同的心理负担回答(虽然我不知道我更喜欢我的...)
猜你喜欢
  • 2017-07-31
  • 2016-01-10
  • 2019-11-18
  • 1970-01-01
  • 2013-11-12
  • 2021-04-25
  • 2020-08-14
  • 2018-08-12
  • 2019-09-28
相关资源
最近更新 更多