我需要做的是转换这样的东西
{'key1': [1, 2, 3], 'key2': [4, 5, 6]}
Run Code Online (Sandbox Code Playgroud)
成
[{'key1': 1, 'key2': 4}, {'key1': 2, 'key2': 5}, {'key1': 3, 'key2': 6}]
Run Code Online (Sandbox Code Playgroud)
值列表的长度可能会有所不同!最快的方法是什么(最好没有for循环)?
Nad*_*mli 11
适用于任意数量的键
>>> map(dict, zip(*[[(k, v) for v in value] for k, value in d.items()]))
[{'key2': 4, 'key1': 1}, {'key2': 5, 'key1': 2}, {'key2': 6, 'key1': 3}]
Run Code Online (Sandbox Code Playgroud)
例如:
d = {'key3': [7, 8, 9], 'key2': [4, 5, 6], 'key1': [1, 2, 3]}
>>> map(dict, zip(*[[(k, v) for v in value] for k, value in d.items()]))
[{'key3': 7, 'key2': 4, 'key1': 1}, {'key3': 8, 'key2': 5, 'key1': 2}, {'key3': 9, 'key2': 6, 'key1': 3}]
Run Code Online (Sandbox Code Playgroud)
适用于任意数量的值或键的通用解决方案:(python2.6)
>>> from itertools import izip_longest
>>> d = {'key2': [3, 4, 5, 6], 'key1': [1, 2]}
>>> map(lambda a: dict(filter(None, a)), izip_longest(*[[(k, v) for v in value] for k, value in d.items()]))
[{'key2': 3, 'key1': 1}, {'key2': 4, 'key1': 2}, {'key2': 5}, {'key2': 6}]
Run Code Online (Sandbox Code Playgroud)
如果你没有python2.6:
>>> d = {'key2': [3, 4, 5, 6], 'key1': [1, 2]}
>>> map(lambda a: dict(filter(None, a)), map(None, *[[(k, v) for v in value] for k, value in d.items()]))
[{'key2': 3, 'key1': 1}, {'key2': 4, 'key1': 2}, {'key2': 5}, {'key2': 6}]
Run Code Online (Sandbox Code Playgroud)
假设键的数量和每个键的值都是任意的并且是先验未知的,当然最简单的方法是使用for循环获得结果:
itit = thedict.iteritems()
k, vs = next(itit)
result = [{k: v} for v in vs]
for k, vs in itit:
for d, v in itertools.izip(result, vs):
d[k] = v
Run Code Online (Sandbox Code Playgroud)
它可能会崩溃,但我对这样做的性能影响持怀疑态度(如果涉及的数据结构非常庞大以至于需要进行性能优化,那么在内存中构建任何超出严格要求的额外辅助结构可能会变得昂贵 - 这我的简单方法是特别小心避免任何这样的中间结构).
编辑:另一种选择,如果整体数据结构很大,特别有趣,但在某些用例中你可能只需要"转换"结构的"点点滴滴",就是构建一个提供所需接口的类,但是这样做"在飞行中",而不是在"大爆炸","一劳永逸"的转变中(如果原始结构可以改变并且转换的结构需要反映原作的当前状态等,这可能特别有用,等等).
当然,出于这样的目的,确定下游代码将使用的"词典列表"的确切功能非常有用.例如,假设你所需要的只是"只读"索引(不改变,迭代,切片,排序......):X[x]必须返回一个字典,其中每个键k映射到一个值,使得(调用O原始字典)列表)X[x][k] is O[k][x].然后:
class Wrap1(object):
def __init__(self, O):
self.O = O
def __getitem__(self, x):
return dict((k, vs[x]) for k, vs in self.O.iteritems())
Run Code Online (Sandbox Code Playgroud)
如果你实际上不需要包装结构来跟踪对原始结构的修改,那么__getitem__也可以"缓存"它返回的字典:
class Wrap2(object):
def __init__(self, O):
self.O = O
self.cache = {}
def __getitem__(self, x):
r = self.cache.get(x)
if r is None:
r = self.cache[x] = dict((k, vs[x]) for k, vs in self.O.iteritems())
return r
Run Code Online (Sandbox Code Playgroud)
请注意,这种方法最终可能会在缓存中出现一些重复,例如,如果O列表中每个都有7个项目,缓存位于x==6并且x==-1最终可能会有两个相同的序列; 如果这是一个问题,你可以,例如,负正常化xs中__getitem__加入len(self.O)出发前给他们.
如果你还需要迭代,以及这个简单的索引,那不是太难:只需添加一个__iter__方法,轻松实现,例如作为一个简单的生成器......:
def __iter__(self, x):
for i in xrange(len(self.O)):
yield self[i]
Run Code Online (Sandbox Code Playgroud)
等等,逐步增加,如果你需要越来越多的列表功能(最坏的情况是,一旦你实现了这个__iter__,你可以构建self.L = list(self)- 恢复到"大爆炸"的方法 - 并且,对于任何进一步的请求,平底船self.L...但你必须做出特别的元类,如果你想要采取这种做法的特殊如方法为好,或用一些微妙的技巧self.__class__ = list; self[:] = self.L,然后适当的del小号;-).
| 归档时间: |
|
| 查看次数: |
2731 次 |
| 最近记录: |