I have four lists that look like this:
lista = [['l', 'k'],['e', '3'],['c', 'k'],['x', 'i'],['d', 'f']]
listanum = [1,2,3,4,5]
listb = [['a', 'k'],['c', 'm'],['v', 'f']]
listbnum = [1,3,4]
lista
and listanum
are synchronized, listb
and listbnum
too.
I want to make a dictionary where the keys are the items in listanum
and the values are items in lista
and listb
, the outcome would be:
di = {1: [['l','k'],['a', 'k']],
2: [['e', '3'],[]],
3:[['c','k'],['c', 'm']],
4: [['x', 'i'],['v', 'f']],
5: [['d', 'f'][]]
}
so if there is no value for a number in listanum in listb, the second list in the dictionarys values is empty.
I have tried this:
di = {}
for i in xrange(len(lista)):
pos = listanum[i]
if pos not in di:
di[pos] = [[],[]]
di[pos][0].append(lista[i])
if i in listbnum:
di[pos][1].append(listb[i])
but get this error message: 'IndexError: list index out of range'
. I cant see why it is out of range???
To calculate the length of a dictionary, we can use the Python built-in len() method. The len() method returns the number of keys in a Python dictionary.
To merge two dictionaries and sum the values: Use a dict comprehension to iterate over one of the dictionaries. On each iteration, use the dict. get() method to sum the values.
To sum the values in a list of dictionaries: Use a generator expression to iterate over the list. On each iteration, access the current dictionary at the specific key. Pass the generator expression to the sum() function.
Zip the items, and use collections.defaultdict
to default the values to list
s:
from itertools import chain
from collections import defaultdict
di = defaultdict(list)
for key, value in chain(zip(listanum, lista), zip(listbnum, listb)):
di[key].append(value)
I used chain
to make looping over both sets of key-value pairs easier; this works in both Python 2 and 3. If this is Python 2 only code, you could use +
to concatenate the two lists.
Output with pprint
and converting back to a regular dict
to make printing easier:
>>> pprint(dict(di))
{1: [['l', 'k'], ['a', 'k']],
2: [['e', '3']],
3: [['c', 'k'], ['c', 'm']],
4: [['x', 'i'], ['v', 'f']],
5: [['d', 'f']]}
This does not create empty lists for the second set; if you have to have empty lists, you are limited to building two separate dictionaries then merging those:
dicta = dict(zip(listanum, lista))
dictb = dict(zip(listbnum, listb))
di = {k: [dicta.get(k, []), dictb.get(k, [])] for k in dicta.viewkeys() | dictb.viewkeys()}
for Python 2, for Python 3 use .keys()
instead of .viewkeys()
, to produce:
>>> pprint(di)
{1: [['l', 'k'], ['a', 'k']],
2: [['e', '3'], []],
3: [['c', 'k'], ['c', 'm']],
4: [['x', 'i'], ['v', 'f']],
5: [['d', 'f'], []]}
Specifically, for your code, you confused i
(the index into lista
) with pos
:
if i in listbnum:
di[pos][1].append(listb[i])
For i = 4
, i in listbnum
is True
, but listb[4]
does not exist. Your code also tried to append the lists from lista
and listb
, which would not result in the correct output.
Altering your version a little to work, using a separate loop for the listb
/listbnum
lists:
di = {}
for i, pos in enumerate(listanum):
if pos not in di:
di[pos] = [[],[]]
di[pos][0][:] = lista[i]
for i, pos in enumerate(listbnum):
di[pos][1][:] = listb[i]
In [7]: da = dict(zip(listanum, lista))
In [8]: db = dict(zip(listbnum, listb))
In [9]: {k:[da.get(k,[]), db.get(k,[])] for k in set(listanum + listbnum)}
Out[9]:
{1: [['l', 'k'], ['a', 'k']],
2: [['e', '3'], []],
3: [['c', 'k'], ['c', 'm']],
4: [['x', 'i'], ['v', 'f']],
5: [['d', 'f'], []]}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With