【问题标题】:List To Dictionary - Improving EfficiencyList To Dictionary - 提高效率
【发布时间】:2017-11-19 00:50:15
【问题描述】:

我正在尝试创建一个采用二维列表并返回字典的函数。我想知道是否有比我写的更有效的方法(例如列表理解/ 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

【问题讨论】:

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


【解决方案1】:
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'}

【讨论】:

  • 是否可以用 [ [1,'a'], [2, 'b'] ..] 来演示如何实现这一点?道歉!
【解决方案2】:

你的函数做的事情太多了:

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

  2. 清理(当前条带化)键和值。同样,只有两者都是字符串时才有意义,这并不保证是这种情况(至少不是来自函数的名称或文档......)。您当然可以测试您的键和/或值是否确实是字符串,但这会增加相当多的开销。再次,调用者有责任进行(最终)清洁。

长话短说,您的函数应该只期望一个数据结构(key=>value 对的序列或 (keys, values) 序列对,并且不应用任何清理,留给调用者提供预期内容的责任。

实际上,从对的序列(或任何可迭代的)构建dict 实际上非常简单,您不需要特殊函数,只需将序列传递给dict 构造函数即可:

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

或者在最近的python版本上使用更快的dict理解:

>>> 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'}

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

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

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

至于您要使用zip() 还是itertools.izip(),这主要取决于您的Python 版本和您的输入。

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

如果你使用的是 Python3.x,zip() 已经变成了一个迭代器,sus 替换了itertools.izip() 所以这个问题变得无关紧要;)

【讨论】:

  • dict 理解和生成器表达式...非常感谢您抽出宝贵时间详细回答这个问题!
猜你喜欢
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 2015-10-08
相关资源
最近更新 更多