在python中转置(旋转)列表的字典[重复]
Posted
技术标签:
【中文标题】在python中转置(旋转)列表的字典[重复]【英文标题】:Transposing (pivoting) a dict of lists in python [duplicate] 【发布时间】: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 正如您在编辑中所承认的那样,这是重复的。如果您有其他问题,那么您应该将其作为一个单独的问题提出,而不是作为次要问题。
【参考方案1】:
使用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 到 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 相同的心理负担回答(虽然我不知道我更喜欢我的...)以上是关于在python中转置(旋转)列表的字典[重复]的主要内容,如果未能解决你的问题,请参考以下文章