2

The problem that I have is hard to explain, easy to understand:

I have a list of tuples:

L=[('a','111'),('b','222'),('a','333'),('b','444')]

from this list I want to createa dictionary where the keys are the first elements of the tuples ('a' and 'b') and the values associated are in a list:

expected output:

{'a':['111','333'],'b':['222','444']}

How can I solve this problem?

d={}
for x in range (len(L)):
    d[L[x][0]]=[L[x][1]]
return d

but as you can easy understand, the output won't be complete since the list will show just the last value associated to that key in L

Jenny
  • 259
  • 1
  • 2
  • 12
  • This exact problems is solved in one of the examples for `collections.defaultdict`: https://docs.python.org/3/library/collections.html#defaultdict-examples – jordanm Jan 31 '20 at 20:34

3 Answers3

6

You can use setdefault() to set the key in the dict the first time. Then append your value:

L=[('a','111'),('b','222'),('a','333'),('b','444')]

d = {}
for key, value in L:
    d.setdefault(key, []).append(value)

print(d)
# {'a': ['111', '333'], 'b': ['222', '444']}
Mark
  • 90,562
  • 7
  • 108
  • 148
  • 1
    Defaultdicts mostly replaced the need for `setdefault` in my experience but this is the way to go if you want to stick to core dicts. – Peter DeGlopper Jan 31 '20 at 20:38
2

You have to append L[x][1] to an existing list, not replace whatever was there with a new singleton list.

d={}
for x in range (len(L)):
    if L[x][0] not in d:
        d[L[x][0]] = []
    d[L[x][0]].append(L[x][1])
return d

A defaultdict makes this easier:

from collections import defaultdict

d = defaultdict(list)
for x in range(len(L)):
    d[L[x][0]].append(L[x][1])
return d

A more idiomatic style of writing this would be to iterate directly over the list and unpack the key and value immediately:

d = defaultdict(list)
for key, value in L:
    d[key].append(value)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • there is no way to remove the 'defaultdict(,' from the output? – Jenny Jan 31 '20 at 21:17
  • You can create a regular dict with `d = dict(d)` once you are done, but typically you don't care about what the string representation of the object itself is. – chepner Jan 31 '20 at 21:32
1

You can try this:

L = [('a','111'),('b','222'),('a','333'),('b','444')]
my_dict = {}

for item in L:
    if item[0] not in my_dict:
        my_dict[item[0]] = []

    my_dict[item[0]].append(item[1])

print(my_dict)

Output:

python your_script.py
{'a': ['111', '333'], 'b': ['222', '444']}

As pointed by @chepner, you can use defaultdict to.

Basically, with defaultdict you'll not need to check if there is no key yet in your dict.

So it would be:

L = [('a','111'),('b','222'),('a','333'),('b','444')]
my_dict = defaultdict(list)

for item in L:
    my_dict[item[0]].append(item[1])

print(my_dict)

And the output:

defaultdict(<class 'list'>, {'a': ['111', '333'], 'b': ['222', '444']})

And if you want to get a dict from the defaultdict, you can simply create a new dict from it:

print(dict(my_dict))

And the output will be:

{'a': ['111', '333'], 'b': ['222', '444']}
Rafael Marques
  • 1,501
  • 15
  • 23