在python中,表达相对于索引运算符的转置的最短路径是什么?
鉴于某些数据结构x
,我希望计算y = transpose(x)
,以便y[a][b] == x[b][a]
。
例如,当x是列表列表时,可以使用
轻松实现y = zip(*x)
但是如果x不是列表,但是例如dict?
{'a': [1,2,3], 'b': [4,5,6], 'c': [7,8,9] }
(编辑:为了澄清,上面的输入应该给出一个行为类似的结构:
[{'a':1, 'b':4, 'c':7}, {'a':2, 'b':5, 'c':8}, {'a':3, 'b':6, 'c':9}]
)
当提前知道会员列表时,我可以做类似
的事情[ {'a': z[0], 'b': z[1], 'c': z[2] } for z in zip(x['a'], x['b'], x['c']) ]
充满冗余和不雅。
我可以像这样写一个完全通用的转置:
class Transpose:
def __init__(self, upper):
self._upper = upper
def __getitem__(self, x):
class Inner:
def __getitem__(ignore, y):
return self._upper[y][x]
return Inner()
但这很冗长且非常不完整(不能正确处理迭代等)。
当然,有一种优雅的方法可以用标准的lib来实现这个目的吗?
答案 0 :(得分:1)
假设数据结构一致(即所有成员列表长度相同),这将有效:
[{k:v[i] for k,v in x.items()} for i in range(len(x.values()[0]))]
迭代成员列表中的索引并创建一个字典,将每个键映射到该索引处的值。真的,我所做的就是采取你的具体例子并概括它。只要您注意到您在字典中引用了特定键,通常可以使用for k,v in dict.items()
上的迭代替换它。
如果您不能依赖数据结构的一致性,那么采用最小长度列表是一个不错的解决方案:
[{k:v[i] for k,v in x.items()} for i in range(min(len(l) for l in x.values()))]
答案 1 :(得分:0)
如果您只是想严格按照自己的方式转换您的词汇列表,那么这将有效:
x = {'a': [1,2,3], 'b': [4,5,6], 'c': [7,8,9] }
[{k:v for k,v in zip(x.keys(),lst)} for lst in x.values()]
结果:
[{'a': 1, 'c': 2, 'b': 3}, {'a': 7, 'c': 8, 'b': 9}, {'a': 4, 'c': 5, 'b': 6}]
至于那些会对任意数据结构进行泛型转换的精辟技巧,我认为这需要更多的工作
答案 2 :(得分:0)
具体来说,假设值是等长的序列:
import itertools as it
d = {'a': [1,2,3], 'b': [4,5,6], 'c': [7,8,9] }
keys = it.repeat(d.keys())
values = it.izip(*d.values())
dT = [dict(it.izip(*thing)) for thing in it.izip(keys, values)]
传递你的身份:
#test
for k, v in d.items():
for n, item in enumerate(v):
print 'd[{}][{}] == dT[{}][{}] | {}'.format(k, n, n, k, d[k][n] == dT[n][k])
assert all(d[k][n] == dT[n][k] for k, v in d.items() for n, _ in enumerate(v))
如果值的长度不同,则无效。