什么是压缩两个嵌套列表单级字典
例如最有效的方法:什么是压缩两个嵌套列表单级字典
list1=['k1','k2','k3',['k4','k5',['k6','k7']]]
list2=['v1','v2','v3',['v4','v5',['v6','v7']]]
,我想将它们合并到一个像这样的词典:
dict1={'k1':'v1','k2':'v2','k3':'v3','k4':'v4','k5':'v5','k6':'v6','k7':'v7'}
我有一个方法来做到这一点,但我认为这需要太多时间:
def mergeToDict(keyList, valueList):
resultDict = {}
for key, value in itertools.izip(keyList, valueList):
if type(key) == list and type(value) == list:
resultDict=dict(resultDict,**mergeToDict(key, value))
elif type(key) != list and type(key) != dict and type(key) != tuple:
resultDict[key] = value
return resultDict
有没有更好的点子?
如果你只有像你提交的用例(嵌套列表,但形状相同),我不认为你需要扁平化。这里是一个办法,至少在我的机器比你快2-3倍(仅再次与约束作品):
def appendDict(list1, list2, resultDict):
for idx, val in enumerate(list1):
if isinstance(val, list):
appendDict(val, list2[idx], resultDict)
else:
resultDict[val] = list2[idx]
list1=['k1','k2','k3',['k4','k5',['k6','k7']]]
list2=['v1','v2','v3',['v4','v5',['v6','v7']]]
resultDict = {}
appendDict(list1, list2, resultDict)
print resultDict
{'k3': 'v3', 'k2': 'v2', 'k1': 'v1', 'k7': 'v7', 'k6': 'v6', 'k5': 'v5', 'k4': 'v4'}
和方法进行了比较:
OP的方法,在运行10000 :0.290050983429
其他提出的方法,对10000个运行:0.580717086792
这种方法,在10000个运行:0.155267000198
也许不是与其他解决方案一样优雅,但表现似乎是这里的主要关注点。
全局变量可以像参数一样传递给函数,它的思想是它只在一个列表上迭代,并且只做一次。 – Bogdan 2012-02-14 14:27:22
这真的很快。也许你可以通过“resultDict”作为参数,看起来更好。 – BackMountainBird 2012-02-14 14:28:53
我会使用某种压扁功能:
def flatten(it):
if isinstance(it, str):
yield it
return
try:
for x in it:
for y in flatten(x):
yield y
except TypeError:
yield it
现在你可以做
from itertools import izip
my_dict = dict(izip(flatten(list1), flatten(list2)))
我觉得这种方式是比较普遍和读者更加透明。
我测试了你的代码,但它似乎比我的代码慢两倍。 – BackMountainBird 2012-02-14 13:28:38
'flatten()'函数有优化的空间 - 例如通过使用'isinstance(it,collections.Iterable)'或'hasattr(it,“__iter __”)'来避免异常,或者只降序到iterable 'list'。这些变化中的大部分都会损害通用性或可读性以获得一点性能。如果性能确实是一个问题,我怀疑这是优化的地方 - 而是首先改变这些列表的创建方式。无论如何,* profile *以确保你在正确的地方进行了优化。 – 2012-02-14 14:00:32
我明白你的观点。 – BackMountainBird 2012-02-14 14:15:03
随着flatten
定义为:
>>> def flatten(l):
... r = []
... for x in l:
... if isinstance(x, list):
... r.extend(flatten(x))
... else:
... r.append(x)
... return r
dict(zip(flatten(list1), flatten(list2)))
似乎是一样快,你的。就像大家说的那样,这种方法更方便。
仍然比我的代码慢一点.. – BackMountainBird 2012-02-14 14:02:51
我喜欢堆栈和发电机功能:
def flatten(seq, *seq_types):
stack = [iter(seq)]
while stack:
for item in stack[-1]:
if isinstance(item, seq_types):
stack.append(iter(item))
break
else:
yield item
else:
stack.pop()
keys = [0, 1, (2, 3, [4.])]
values = (5, 6, (7, "joe", [9]))
print dict(zip(flatten(keys, list, tuple), flatten(values, tuple, list)))
结果:
{0: 5, 1: 6, 2: 7, 3: 'joe', 4.0: 9}
或者,如果你肯定知道的输入列表具有相同的结构,这也可能工作:
def flatten(seq, *seq_types):
seq = list(seq)
for item in seq:
if isinstance(item, seq_types):
seq.extend(item)
else:
yield item
注意物品的顺序可能会改变:
print list(flatten([1, 2, [3, 4, [5]]], list))
print list(flatten([1, 2, [[3, 4], 5]], list))
结果:
[1, 2, 3, 4, 5]
[1, 2, 5, 3, 4]
您的解决方案看起来比所有下面的答案更好。 – jterrace 2012-02-14 14:24:21