[英]Iterate over list of values dictionary
I have a dict like this 我有这样的字典
data = {
'a': [95, 93, 90],
'b': [643, 611, 610]
}
I want to iterate over the dict and fetch key and value from list of values for each item, something like this 我想迭代dict并从每个项的值列表中获取键和值,类似这样
{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}
I have implemented the logic for this and it works fine, but when i see the temp_dict
created in process, i see lots of intermediate unnecessary looping. 我已经为此实现了逻辑并且它工作正常,但是当我看到在进程中创建的
temp_dict
,我看到许多中间不必要的循环。 The end result works just fine but i think it can be improved a lot. 最终的结果很好,但我认为它可以改进很多。
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)
How to do it more efficiently? 如何更有效地做到这一点?
Try something like this - 尝试这样的事情 -
>>> 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}]
When passing a list using * as a parameter to a function, it will break the list into individual elements and pass it onto the function. 当使用*作为参数将列表传递给函数时,它会将列表分解为单个元素并将其传递给函数。 Example - if we pass
[[1,2],[3,4]]
it would be passed as two different arguments - [1,2]
and [3,4]
- checkt this here (Section - * in Function calls) 示例 - 如果我们传递
[[1,2],[3,4]]
它将作为两个不同的参数传递 - [1,2]
和[3,4]
- 在此处检查 (部分 - 函数调用中的*)
Example to explain this - 举例解释一下 -
>>> 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 - This function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. zip - 此函数返回元组列表,其中第i个元组包含来自每个参数序列或迭代的第i个元素。
A bit more scale-able model - 更具规模的模型 -
>>> 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}]
A fun way to do it with a list comprehension. 一种有趣的方式来实现列表理解。
>>> 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}]
Or a more traditional (less fun) way 或者更传统(不太有趣)的方式
>>> 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}]
And per comments, here is a way to do it without relying on 'non-guaranteed' behavior like the same ordering of data.keys() and data.values(). 根据评论,这里有一种方法可以不依赖于“非保证”行为,如data.keys()和data.values()的相同顺序。
List Comprehension 列表理解
>>> 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}]
And traditional for-loop 和传统的for循环
>>> 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}]
Something similar to this (but replace the print with a yield): 类似于此的东西(但用产量替换印刷品):
keys = []
values = []
for k, v in data.iteritems():
keys.append(k)
values.append(v)
for vals in zip(*values):
print dict(zip(keys, vals))
The zip(*values)
in the second for-loop more or less transposes the list of lists in values
. 第二个for循环中的
zip(*values)
或多或少地将 values
列表转换为列表。 Slightly more compact way of writing the same: 略微更紧凑的写作方式:
keys = list(data)
for vals in zip(*data.values()):
print dict(zip(keys, vals))
In both cases, the result is: 在这两种情况下,结果是:
{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}
If the number and actual literals used as keys are not known at coding time, here's an idea: 如果在编码时不知道用作键的数字和实际文字,这里有一个想法:
you can yield a series of dict-like objects. 你可以产生一系列类似dict的对象。 Each instance would expose the the i-th value from the value list.
每个实例都会从值列表中公开第i个值。 You can read about emulating python container types .
您可以阅读有关模拟python容器类型的信息 。
This is one way to do it: 这是一种方法:
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]}
Output: 输出:
{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.