user6917220
user6917220

Reputation: 21

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!

Upvotes: 1

Views: 150

Answers (4)

mgilson
mgilson

Reputation: 310147

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.

Upvotes: 4

wwii
wwii

Reputation: 23773

Using itertools and zip:

import itertools
d = {"a":[1,2,3], "b":[4,3,5,6,7], "c":[1], "d":[2,5]}
result = []
for k, v in d.items():
    result.extend(zip(itertools.cycle(k), v))

or:

for k, v in d.items():
    result.extend(itertools.izip(itertools.cycle(k), v))

itertools.repeat could also be used in place of itertools.cycle.

Upvotes: 0

sytech
sytech

Reputation: 41119

new_list = []
for key, values in mydict.items():
    for val in values:
        new_list.append((key, val))

Upvotes: 0

A.Kot
A.Kot

Reputation: 7913

You should avoid for loops in python where possible, its very inefficient. Use list comprehension as the most pythonic way to do this. stack is the name of the dict:

[(i,x) for x in stack[i] for i in stack.keys()]

Upvotes: 0

Related Questions