Python creates one dictionary from a list of keys and a list of lists of values

So, I have a list of keys:

keys = ['id','name', 'date', 'size', 'actions']

      

and I also have a list of vales lists:

values=
    [
        ['1','John','23-04-2015','0','action1'],
        ['2','Jane','23-04-2015','1','action2']
    ]

      

How can I build a dictionary with those keys that match the values?

The output should be:

{
    'id':['1','2'],
    'name':['John','Jane'],
    'date':['23-04-2015','23-04-2015'],
    'size':['0','1'],
    'actions':['action1','action2']
}

      

EDIT: I tried using zip () and dict (), but this will only work if the list of values ​​has 1 list, i.e. values = [['1','John','23-04-2015','0','action1']]

for list in values:
    dic = dict(zip(keys,list))

      

I also thought about initializing dic with keys and then built the list of values ​​myself, but I felt there should be an easier way to do this.

dic = dict.fromkeys(keys)

for list in values:
    ids = list[0]
    names = list[1]
    dates = list[2]
    sizes = list[3]
    actions = list[4]

      

and then finally

dic['id'] = ids
dic['name'] = names
dic['date'] = dates
dic['size'] = sizes
dic['action'] = actions

      

It seemed really silly and I was wondering what is the best way to do it.

+3


source to share


1 answer


>>> keys = ['id','name', 'date', 'size', 'actions']
>>> values = [['1','John','23-04-2015','0','action1'], ['2','Jane','23-04-2015','1','action2']]
>>> c = {x:list(y) for x,y in zip(keys, zip(*values))}
>>> c
{'id': ['1', '2'], 'size': ['0', '1'], 'actions': ['action1', 'action2'], 'date': ['23-04-2015', '23-04-2015'], 'name': ['John', 'Jane']}
>>> print(*(': '.join([item, ', '.join(c.get(item))]) for item in sorted(c, key=lambda x: keys.index(x))), sep='\n')
id: 1, 2
name: John, Jane
date: 23-04-2015, 23-04-2015
size: 0, 1
actions: action1, action2

      

This uses several tools:

c

created with vocabulary comprehension. Comprehension is another way of expressing iteration, like a dictionary or a list. Instead of initializing an empty iteration and then using a loop to add elements to it, comprehension moves those syntax structures around.

result = [2*num for num in range(10) if num%2]

      

equivalent to

result = []
for num in range(10):
    if num%2: # shorthand for "if num%2 results in non-zero", or "if num is not divisible by 2"
        result.append(2*num)

      

and we get [2, 6, 10, 14, 18]

.

zip()

creates a tuple generator where each element of each tuple is the corresponding element of one of the arguments passed to zip()

.

>>> list(zip(['a','b'], ['c','d']))
[('a', 'c'), ('b', 'd')]

      

zip()

takes multiple arguments - if you pass it one large list containing smaller sublists, the result is different:

>>> list(zip([['a','b'], ['c','d']]))
[(['a', 'b'],), (['c', 'd'],)]

      

and not at all what we want. However, our list values

is just such a list: a large list containing signatures. We want zip()

these sublists. This is a great time to use the operator *

.



The operator *

is an "unpacked" iteration.

>>> print(*[1,2,3])
1 2 3
>>> print(1, 2, 3)
1 2 3

      

It is also used in function definitions:

>>> def func(*args):
...    return args
...
>>> func('a', 'b', [])
('a', 'b', [])

      

So, to create a dictionary, we zip()

concatenate lists of values ​​and then zip()

with keys. We then iterate over each of these tuples and create a dictionary from them, with each element of the first tuple being a key and the second element being a value (other than list

instead of tuple

).

To print this, we could create a large loopback structure, or create generators (faster to collect and process than full data structures like list

) and loop through them, which allows us to use *

things to unpack. Remember that in Python 3 it print

can take multiple arguments as shown above.

First, we'll sort the dictionary using each element's position in keys

as a key. If we use something like key=len

it sends each element to a function len()

and uses the returned length as the key. We use lambda

to determine the built-in, an unnamed function that takes an argument x

, and return

x

in the list

of keys

. Note that the dictionary is not actually sorted; we just set it up so we can go through it according to the sort order.

We can then go through this sorted dictionary and collect its elements into printable strings. At the top level, we have a join()

key with its value separated ': '

. Each value has join()

ed c elements ', '

. Note that if the elements weren't strings, we would have to turn them into strings in order join()

to work.

>>> list(map(str, [1,2,3]))
['1', '2', '3']
>>> print(*map(str, [1,2,3]))
1 2 3

      

A generator that yield

, each of these join()

ed lines is then decompressed by an operator *

, and each element is sent as an argument print()

, specifying a delimiter '\n'

(newline) instead of the default ' '

(space).

It's perfectly fine to use loops instead of concepts and *

and then rearrange them into structures like this after your logic is functional, if you like. This is not particularly necessary most of the time. Comprehension is sometimes slightly faster than equivalent loops, and with practice, you may prefer the syntax of the concepts. Learn the operator *

, although it is an extremely versatile tool for defining functions. Also have a look **

(often called "double star" or "kwargs"), which unpacks dictionaries into keyword arguments and can also be used to define functions.

+7


source







All Articles