List dictionary of meaning words
I have such a recorder
data = {
'a': [95, 93, 90],
'b': [643, 611, 610]
}
I want to iterate over the dict and fetch key and value from the list of values for each item, something like this
{'a': 95, 'b': 643}
{'a': 93, 'b': 611}
{'a': 90, 'b': 610}
I've implemented the logic for this and it works great, but when I see temp_dict
it created in the process, I see a lot of unnecessary loops in between. The end result works great, but I think it could 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 can you do this more efficiently?
source to share
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 function parameter, it splits the list into individual elements and passes it to the function. Example. If we go through [[1,2],[3,4]]
it will be passed as two different arguments - [1,2]
and [3,4]
- check here here (section - * in function calls)
An 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 sequence of arguments or iterations.
A slightly more scalable 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}]
source to share
A fun way to do this is 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 in the comments, here's a way to do it without relying on "not guaranteed" behavior like the same data ordering .keys () and data.values ().
List Description
>>> 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 the cycle
>>> 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}]
source to share
Something similar to this (but replace print with output):
keys = []
values = []
for k, v in data.iteritems():
keys.append(k)
values.append(v)
for vals in zip(*values):
print dict(zip(keys, vals))
zip(*values)
in the second, the for-loop more or less wraps the list of lists into values
. A slightly more compact way of writing:
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}
source to share
If the number and the actual literals used as keys are not known during encoding, here's the idea:
you can give a series of dict-like objects. Each instance will print the i-th value from the list of values. You can read the python container types emulation .
source to share