Reputation: 3669
I have a dict-
a = {'b': [1,2,3], 'c':[4,5,6]}
I want to use list comprehension only to achieve this output-
[['c', 4], ['c', 5], ['c', 6], ['b', 1], ['b', 2], ['b', 3]]
A simple for loop gets it done with -
x = []
for k, v in a.iteritems():
for i in v:
x.append([k, i])
Tried to convert it to list comprehension, I did this-
[[k,i] for i in v for k, v in a.items()]
But weirdly for me, I got an output
[['c', 1], ['b', 1], ['c', 2], ['b', 2], ['c', 3], ['b', 3]]
What should be the right list comprehension and why is my list comprehension not working?
Upvotes: 3
Views: 5102
Reputation:
you can try to use itertools.product
from itertools import product, chain
a = {'b': [1,2,3], 'c':[4,5,6]}
list(chain(*[product(k, v) for k, v in a.items()]))
result is
[('b', 1), ('b', 2), ('b', 3), ('c', 4), ('c', 5), ('c', 6)]
if you strongly need the list of lists, you can do
list(chain(*[[list(item) for item in product(k, v)] for k, v in a.items()]))
the output is:
[['b', 1], ['b', 2], ['b', 3], ['c', 4], ['c', 5], ['c', 6]]
and some tests of the perfomance
In [6]: %timeit [[i, j] for i in a for j in a[i]]
618 ns ± 5.34 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [7]: %timeit list(chain(*[product(k, v) for k, v in a.items()]))
1.26 µs ± 19.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [8]: %timeit list(chain(*[[list(item) for item in product(k, v)] for k, v in a.items()]))
2.61 µs ± 49.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Upvotes: 1
Reputation: 2130
b = [[i, j] for i in a for j in a[i]]
for nested for
loops in list comprehension the first loop will be the one whose variable you will be using in the second one, like here for example i
is used in the second loop, nested for loops in list comprehensions are hard to read therefore you should better avoid it.
Upvotes: 8
Reputation: 5224
You should get k,v
first, then iterate over v :
a = {'b': [1,2,3], 'c':[4,5,6]}
print([[k,i] for k, v in a.items() for i in v])
output :
[['c', 4], ['c', 5], ['c', 6], ['b', 1], ['b', 2], ['b', 3]]
Note :
In [[k,i] for i in v for k, v in a.items()]
, v
is not defined when you try to iterate over it.
@Skam has a great example for this : how to interpret double for loop comprehension
# Without list comprehension
list_of_words = []
for sentence in text:
for word in sentence:
list_of_words.append(word)
return list_of_words
is equivalent to :
[word for sentence in text for word in sentence]
Upvotes: 4
Reputation: 5713
You were almost there. The main problem you were facing is due to the order of the for loop.
The order of for loop inside the list comprehension is based on the order in which they appear in traditional loop approach. Outer most loop comes first, and then the inner loops subsequently.
a = {'b': [1,2,3], 'c':[4,5,6]}
x = []
for k, v in a.items():
for i in v:
x.append([k, i])
print(x)
print([[k,i] for i in v for k, v in a.items()])
print([[k,i] for k, v in a.items() for i in v])
OUTPUT
[['b', 1], ['b', 2], ['b', 3], ['c', 4], ['c', 5], ['c', 6]]
[['b', 4], ['c', 4], ['b', 5], ['c', 5], ['b', 6], ['c', 6]]
[['b', 1], ['b', 2], ['b', 3], ['c', 4], ['c', 5], ['c', 6]]
Upvotes: 3