列表到字典 - 提高效率

时间:2017-06-16 09:38:54

标签: python list python-3.x loops dictionary

我正在尝试创建一个采用二维列表并返回字典的函数。我想知道是否有更有效的方式而不是我写的(例如list comprehension / itertools?)我对python相对较新,并且已经阅读了一些关于列表理解和itertools doc(https://stackoverflow.com/questions/16548668/iterating-over-a-2-dimensional-python-list)的例子但是可以好像是把它实现到这块代码中。

任何帮助将不胜感激。谢谢!

def listToDict(self, lstInputs):        
    dictOutput = dict()
    rows = len(lstInputs)
    cols = len(lstInputs[0])
    if rows == 2:
        for x in range(rows):
            if lstInputs[0][x] is not None:
                if lstInputs[1][x] is not None:
                    dictOutput[lstInputs[0][x].strip()] = lstInputs[1][x].strip()
                else:
                    dictOutput[lstInputs[0][x].strip()] = lstInputs[1][x]
    elif cols == 2:
        for x in range(rows):
            if lstInputs[x][0] is not None:
                if lstInputs[x][1] is not None:
                    dictOutput[lstInputs[x][0].strip()] = lstInputs[x][1].strip()
                else:
                    dictOutput[lstInputs[x][0].strip()] = lstInputs[x][1]
    else:
        pass

    return dictOutput

2 个答案:

答案 0 :(得分:2)

你的功能做得太多了:

  1. 试图找出它的输入是一系列key =>值对还是一对键,值序列。这是不可靠的。不要试图猜测,调用者有责任传递正确的结构,因为只有调用者知道他想要变成一个字典的数据。

  2. 清洁(当前条带化)键和值。在这里,只有两者都是字符串才有意义,但不保证是这种情况(至少不是来自函数的名称或文档......)。您当然可以测试您的密钥和/或值是否确实是字符串,但这会增加一些开销。这也是呼叫者有责任进行(最终)清洁。

  3. 长话短说,你的函数应该只期望一个数据结构(一系列key =>值对或一对(键,值)序列,并且不应用任何清理,留在呼吁提供预期的责任。

    实际上,从序列(或任何可迭代的)对构建dict实际上是如此微不足道,以至于您不需要特殊的函数,只需将序列传递给{{1}即可。构造函数:

    dict

    或者在使用dict理解的更新的python版本上可以更快:

    >>> lst_of_pairs = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
    >>> dict(lst_of_pairs) 
    {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
    

    那么,你的第一个构建块是内置的,不需要任何特殊的功能。

    请注意,这适用于任何迭代,只要1.它只产生对和2.键(对的第一项)是唯一的。因此,如果你想在构建dict之前应用一些清理,你可以使用生成器函数或表达式来执行它,即如果调用者知道所有键都是字符串并且可能需要条带化并且所有值都是需要条带化的字符串或{{ 1}},您可以传递生成器表达式而不是源列表,即:

    >>> lst_of_pairs = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
    >>> {k:v for k, v in lst_of_pairs} 
    {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
    

    最后,将一对键,值序列转换为一系列key =>值对是内置None及其惰性版本>>> lst_of_pairs = [(" a ", "1 "), ("b ", None), ("c", " fooo ")] >>> {k.strip(): v if v is None else v.strip() for k, v in lst_of_pairs} {'a': '1', 'c': 'fooo', 'b': None} 的用途:

    zip()

    把它放在一起,最“狡猾”的情况(从一系列键和一系列值构建一个字典,将条带应用于键并条件化地将条带应用于值)可以表示为:

    itertools.izip()

    如果是一次性使用,那实际上就是你所需要的。

    现在,如果您有一个用例,您知道必须在代码中的不同位置应用此方法,并且始终使用相同的清单但是列表对或列表对,您当然希望将其分解出来尽可能 - 但不是更多:

    >>> keys = [' a ', 'b ', 'c']
    >>> values = ['1 ', None, ' fooo ']
    >>> zip(keys, values)
    [(' a ', '1 '), ('b ', None), ('c', ' fooo ')]
    >>> list(itertools.izip(keys, values))
    [(' a ', '1 '), ('b ', None), ('c', ' fooo ')]
    

    然后将其留给调用者,以便在需要时应用>>> {k.strip(): v if v is None else v.strip() for k, v in itertools.izip(keys, values)} {'a': '1', 'c': 'fooo', 'b': None}

    def to_dict(pairs):
        return {
            k.strip(): v if v is None else v.strip()) 
            for k, v in lst_of_pairs
            }
    

    至于你想要使用zip()还是def func1(): keys = get_the_keys_from_somewhere() values = get_the_values_too() data = to_dict(itertools.izip(keys, values)) do_something_with(data) def func2() pairs = get_some_seqence_of_pairs() data = to_dict(pairs) do_something_with(data) ,它主要取决于你的Python版本和你的输入。

    如果您使用的是Python 2.x,zip()将在内存中构建一个新列表,而itertools.izip()将在懒惰的情况下构建它,因此使用zip()会产生轻微的性能开销,但是如果您正在处理大型数据集,它将节省大量内存。

    如果您使用的是Python3.x,itertools.izip()已经变成了迭代器,则替换itertools.izip()以使问题变得无关紧要;)

答案 1 :(得分:0)

l = [[1,2,3],['a','b','c']]

def function(li):
    d = {}
    for num in zip(li[0],li[1]):
        d[num[0]] = num[1]
    print(d)
function(l)
out put:
{1: 'a', 2: 'b', 3: 'c'}