1

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!

1
  • Where is pmid coming from? Commented Oct 21, 2016 at 14:44

4 Answers 4

4

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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()]

3 Comments

You don't need to call .keys
Yes you are correct. Just helps to see whats going on. Especially when I use random names like 'stack' for my dictionary.
I disagree with the assertion that "you should avoid for loops ..." because they're inefficient. At worst, they're only marginally slower than an equivalent list comprehension. The primary concern is typically how easy the expression is to read until your profiling can tell you otherwise. List-comps frequently shine here because they can be digested as a single atomic unit for those who are familiar with them.
0
new_list = []
for key, values in mydict.items():
    for val in values:
        new_list.append((key, val))

3 Comments

How does this solution differ from the solution posted a few minutes ago?
Woops, I guess I was beat to the punch.
While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please include an explanation for your code, as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Flaggers / reviewers: For code-only answers such as this one, downvote, don't delete!
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.