迭代值列表字典

时间:2015-06-24 05:55:54

标签: python dictionary

我有这样的词典

data = {
    'a': [95, 93, 90],
    'b': [643, 611, 610]
}

我想迭代dict并从每个项的值列表中获取键和值,类似这样

{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}

我已经为此实现了逻辑并且它工作正常,但是当我看到正在创建的temp_dict时,我看到许多中间不必要的循环。最终结果很好,但我认为它可以改进很多。

import timeit

data = {
    'a': [95, 93, 90],
    'b': [643, 611, 610]
}


def calculate(**kwargs):
    temp_dict = {}
    index = 0
    len_values = list(kwargs.values())[0]

    while index < len(len_values):
        for k, v in kwargs.items():
            temp_dict[k] = v[index]
        index += 1
        yield temp_dict


start_time = timeit.default_timer()
for k in (calculate(**data)):
    print(k)
print(timeit.default_timer() - start_time)

如何更有效地完成工作?

5 个答案:

答案 0 :(得分:13)

尝试这样的事情 -

>>> data = {
...     'a': [95, 93, 90],
...     'b': [643, 611, 610]
... }
>>> lst = list(data.items())
>>> lst1 = list(zip(*[i[1] for i in lst]))
>>> lst1
[(95, 643), (93, 611), (90, 610)]
>>> newlist = []
>>> for aval, bval in lst1:
...     newlist.append({lst[0][0]:aval , lst[1][0]:bval})
...
>>> newlist
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

当使用*作为参数将列表传递给函数时,它会将列表分成单个元素并将其传递给函数。示例 - 如果我们传递[[1,2],[3,4]],它将作为两个不同的参数传递 - [1,2][3,4] - 检查此here(部分 - 函数调用中的*)

解释这个的例子 -

>>> lst = [[1,2,3],[4,5,6],[7,8,9]]
>>> def func(a, b, c):
...     print(a)
...     print(b)
...     print(c)
...
>>> func(*lst)
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

zip - 此函数返回元组列表,其中第i个元组包含来自每个参数序列或迭代的第i个元素。

更具可扩展性的模型 -

>>> lst = list(data.items())
>>> lst
[('a', [95, 93, 90]), ('b', [643, 611, 610])]
>>> lst1 = list(zip(*[i[1] for i in lst]))
>>> lst1
[(95, 643), (93, 611), (90, 610)]
>>> newlist = []
>>> for x in lst1:
...     d = {}
...     for i,y in enumerate(lst):
...             d[y[0]] = x[i]
...     newlist.append(d)
...
>>> newlist
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

答案 1 :(得分:4)

使用列表理解来实现它的有趣方式。

>>> data = {
'a': [95, 93, 90],
'b': [643, 611, 610]
}
>>> [dict(zip(data, x)) for x in zip(*data.values())] 
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

或者更传统(不太有趣)的方式

>>> result = []
>>> for tuple_ in zip(*data.values()):
...     d = {}
...     for key, val in zip(data, tuple_):
...         d[key] = val
...     result.append(d)
>>> print result
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

根据评论,这是一种不依赖于“无保证”的方法。行为与data.keys()和data.values()的相同排序。

列表理解

>>> keys, values = zip(*data.items())
>>> [dict(zip(keys, tuple_)) for tuple_ in zip(*values)]
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

传统的for-loop

>>> result = []
>>> keys, values = zip(*data.items())
>>> for tuple_ in zip(*values):
...     d = {}
...     for key, val in zip(keys, tuple_):
...         d[key] = val
...     result.append(d)
>>> print result
[{'a': 95, 'b': 643}, {'a': 93, 'b': 611}, {'a': 90, 'b': 610}]

答案 2 :(得分:1)

与此类似的东西(但用收益率替换印刷品):

keys = []
values = []
for k, v in data.iteritems():
    keys.append(k)
    values.append(v)
for vals in zip(*values):
    print dict(zip(keys, vals))

第二个for循环中的zip(*values)或多或少transposes values中的列表列表。略微更紧凑的写作方式:

keys = list(data)
for vals in zip(*data.values()):
    print dict(zip(keys, vals))

在这两种情况下,结果都是:

{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}

答案 3 :(得分:1)

如果在编码时不知道用作键的数字和实际文字,这里有一个想法:

你可以产生一系列类似dict的对象。每个实例都会从值列表中公开第i个值。您可以阅读emulating python container types

答案 4 :(得分:0)

这是一种方法:

data = {
    'a': [95, 93, 90],
    'b': [643, 611, 610]
}

x = data.values()
d1 = {'a':x[0][0], 'b':x[1][0]}
d2 = {'a':x[0][1], 'b':x[1][1]}
d3 = {'a':x[0][2], 'b':x[1][2]}

输出:

{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}