Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List Comprehension of Lists Nested in Dictionaries

I have a dictionary where each value is a list, like so:

dictA = {1:['a','b','c'],2:['d','e']}

Unfortunately, I cannot change this structure to get around my problem

I want to gather all of the entries of the lists into one single list, as follows:

['a','b','c','d','e']

Additionally, I want to do this only once within an if-block. Since I only want to do it once, I do not want to store it to an intermediate variable, so naturally, a list comprehension is the way to go. But how? My first guess,

[dictA[key] for key in dictA.keys()]

yields,

[['a','b','c'],['d','e']]

which does not work because

'a' in  [['a','b','c'],['d','e']]

yields False. Everything else I've tried has used some sort of illegal syntax.

How might I perform such a comprehension?

like image 930
wnnmaw Avatar asked Nov 04 '13 20:11

wnnmaw


People also ask

Can list comprehension be nested?

As it turns out, you can nest list comprehensions within another list comprehension to further reduce your code and make it easier to read still. As a matter of fact, there's no limit to the number of comprehensions you can nest within each other, which makes it possible to write very complex code in a single line.

Can we use list comprehension in dictionary?

Using dict() method we can convert list comprehension to the dictionary. Here we will pass the list_comprehension like a list of tuple values such that the first value act as a key in the dictionary and the second value act as the value in the dictionary.

Can list be nested in dictionary Python?

A Python dictionary can contain a list as the value portion of a key-value pair entry.

Can I implement nested dictionary with list?

Given a list and dictionary, map each element of list with each item of dictionary, forming nested dictionary as value. Explanation : Index-wise key-value pairing from list [8] to dict {'Gfg' : 4} and so on.


2 Answers

Loop over the returned list too (looping directly over a dictionary gives you keys as well):

[value for key in dictA for value in dictA[key]]

or more directly using dictA.itervalues():

[value for lst in dictA.itervalues() for value in lst]

List comprehensions let you nest loops; read the above loops as if they are nested in the same order:

for lst in dictA.itervalues():
    for value in lst:
        # append value to the output list

Or use itertools.chain.from_iterable():

from itertools import chain

list(chain.from_iterable(dictA.itervalues()))

The latter takes a sequence of sequences and lets you loop over them as if they were one big list. dictA.itervalues() gives you a sequence of lists, and chain() puts them together for list() to iterate over and build one big list out of them.

If all you are doing is testing for membership among all the values, then what you really want is to a simple way to loop over all the values, and testing your value against each until you find a match. The any() function together with a suitable generator expression does just that:

any('a' in lst for lst in dictA.itervalues())

This will return True as soon as any value in dictA has 'a' listed, and stop looping over .itervalues() early.

like image 167
Martijn Pieters Avatar answered Oct 06 '22 20:10

Martijn Pieters


If you're actually checking for membership (your a in... example), you could rewrite it as:

if any('a' in val for val in dictA.itervalues()):
    # do something

This saves having to flatten the list if that's not actually required.

like image 21
Jon Clements Avatar answered Oct 06 '22 22:10

Jon Clements