将两个嵌套列表压缩到单个级别字典的最有效方法是什么

Bac*_*ird 6 python dictionary list

例如:

list1=['k1','k2','k3',['k4','k5',['k6','k7']]]
list2=['v1','v2','v3',['v4','v5',['v6','v7']]]
Run Code Online (Sandbox Code Playgroud)

我想将它们合并到这样的字典中:

dict1={'k1':'v1','k2':'v2','k3':'v3','k4':'v4','k5':'v5','k6':'v6','k7':'v7'}
Run Code Online (Sandbox Code Playgroud)

我有办法做到这一点,但我认为这需要太多时间:

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
Run Code Online (Sandbox Code Playgroud)

有没有更好的想法?

Sve*_*ach 5

我会使用某种扁平功能:

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
Run Code Online (Sandbox Code Playgroud)

现在你可以做到

from itertools import izip
my_dict = dict(izip(flatten(list1), flatten(list2)))
Run Code Online (Sandbox Code Playgroud)

我认为这种方式对于读者来说更通用,更透明.

  • 在`flatten()`函数中有优化空间 - 例如通过使用`isinstance(it,collections.Iterable)`或`hasattr(it,"__iter __")`来避免异常,或者只是降序为类型为`的迭代list`.大多数这些更改都会损害通用性或可读性,从而获得一点点性能.如果性能确实是一个问题,我怀疑这是优化的地方 - 而不是首先改变这些列表的创建*.在任何情况下,*profile*以确保您在正确的位置进行优化. (3认同)

Bog*_*dan 1

我认为如果您只有像您提出的用例(嵌套列表但具有相同形状)这样的用例,那么您根本不需要展平。这是一种方法,至少在我的机器上比你的机器快 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'}
Run Code Online (Sandbox Code Playgroud)

以及方法的比较:

OP 的方法,运行 10000 次:0.290050983429

其他建议的方法,10000 次运行:0.580717086792

此方法运行 10000 次:0.155267000198

也许不如其他解决方案那么优雅,但性能似乎是这里的主要问题。

  • 全局变量可以作为参数传递给函数,其想法是它仅迭代其中一个列表,并且只迭代一次。 (2认同)