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?

+3


source to share


5 answers


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

      

+13


source


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

      

+4


source


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}

      

+1


source


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 .

+1


source


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}

      

0


source







All Articles