user6917220 user6917220 - 1 month ago 4
Python Question

Retrieve dict values from a list in Python

I have a dictionary where the values are lists of different lengths like so:

{"a":[1,2,3], "b":[4,3,5,6,7], "c":[1], "d":[2,5]}


I would like to convert it to a list of tuples for upload to a database:

[("a",1), ("a",2), ("a",3), ("b",4), ("b",3) ... ]


The most recent thing I have tried is:

lst = []
mydict = {"a":[1,2,3], "b":[4,3,5,6,7], "c":[1], "d":[2,5]}
for k in mydict.keys():
for i in range(len(mydict[k])):
count = 0
while count < i:
lst.append((k, mydict[k]))
count += 1


This does not work, but I can't tell why. Thanks for any help!

Answer

It feels like you're over-complicating it a bit...

It should only require 2 loops:

lst = []
for k, vals in mydict.items():
    for value in vals:
        lst.append((k, value))

The first loop is over the dictionary items, the inner loop is over the values list. For each value in the values list, just append a tuple that holds the key and the value to your resultant list.

And, FWIW, there are lots of other spellings here:

lst = []
for k, vals in mydict.items():
    lst.extend((k, value) for value in vals)

Or even a 1-liner:

lst = [(k, value) for k, vals in mydict.items() for value in vals]

though I'm not a huge fan of the 1-line version...


As for why your version doesn't work, let's take a look and find out:

lst = []
mydict = {"a":[1,2,3], "b":[4,3,5,6,7], "c":[1], "d":[2,5]}
for k in mydict.keys():
    for i in range(len(mydict[k])):
        count = 0
        while count < i:
            lst.append((k, mydict[k]))
            count += 1

The first thing that we see is you have an extra loop. For each key, you'll be hitting some of the values twice when you only want to hit them once. You could fix it by removing the loop over range(len(...)):

lst = []
mydict = {"a":[1,2,3], "b":[4,3,5,6,7], "c":[1], "d":[2,5]}
for k in mydict.keys():
    count = 0
    while count < len(mydict[k]):
        lst.append((k, mydict[k]))
        count += 1

But, this is already a more verbose (and, IMHO, confusing) way to write it out than the options I've provided above.

Comments