python中的泛型转置

python中的泛型转置,python,Python,在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

在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()
但这是冗长且非常不完整的(不能正确地处理迭代等)


当然,有一种优雅的方法可以通过标准库实现这一点吗?

如果你只是想把你的dict列表严格地转换成你现有的方式,这将起作用:

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()]
[{k:v[i] for k,v in x.items()} for i in range(len(x.values()[0]))]
结果:

[{'a': 1, 'c': 2, 'b': 3}, {'a': 7, 'c': 8, 'b': 9}, {'a': 4, 'c': 5, 'b': 6}]

至于能在任意数据结构上进行泛型转换的精练方法,我认为对于字典来说需要做更多的工作,特别是假设值是等长的序列:

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

如果值的长度不同,则不起作用。

假设数据结构一致(即所有成员列表的长度相同),这将起作用:

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()]
[{k:v[i] for k,v in x.items()} for i in range(len(x.values()[0]))]
迭代成员列表中的索引,并创建一个字典,将每个键映射到该索引处的值。真的,我所做的就是拿你的例子来概括。当您注意到正在引用字典中的特定键时,通常可以用dict.items()中k,v的
迭代替换它

如果您不能依赖数据结构的一致性,那么采用最小长度列表是一个不错的解决方案:

[{k:v[i] for k,v in x.items()} for i in range(min(len(l) for l in x.values()))]

总是2D?第二维度中的所有内容是否都相同(例如,没有列表和目录的混合列表)?“使用标准库肯定有一种优雅的方法来实现这一点?”-您是否期望
转置所有内容
?原则上,可以使用map()的序列将工作2D版本应用到更深层次,并且气泡排序算法可用于生成多个索引的任何排列,如果你真的需要的话。我不太在乎背后的实际类型;重要的是合理的行为。我提到的身份(y[a][b]==x[b][a])这不符合他的具体例子的要求,但可能他的例子根本不是他想要的。@Gerrat,也许我误解了。这不符合他的具体例子的要求,但可能他的例子根本不是他想要的。–也谢谢,那也不是我想要的。至少你让我发现了对dict的理解:)不同长度的情况是考虑到zip()的良好行为的地方;我的第一个版本还具有使用生成器的优点。我仍然希望有人能在标准库中提供一个更干净、更通用的版本,但你的答案是目前为止最好的。你希望支持的生成器的输出是什么?无法从生成器返回字典项,因为字典未排序。