0

Let's say there is a dictionary that has strings mixed with lists:

dictionary = {'item_a': 'one',
              'item_b': 'two',
              'item_c': ['three', 'four'],
              'item_d': 'five'}

and the result should be:

['one', 'two', 'three', 'four', 'five']

How can it be achieved by using list comprehension?

The following gives only the values for the list, but it's missing the strings that are not a list and else does not work if added right after the if:

[val for sublist in dictionary.values() if type(sublist) is list for val in sublist]
  • I think the answer you might be looking for could be found here: https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python – Fallenreaper Jul 25 '17 at 04:17
  • Possible duplicate of [Making a flat list out of list of lists in Python](https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python) – Fallenreaper Jul 25 '17 at 04:17
  • 1
    You are going to have issues with this because dictionaries are unordered data structures. – GWW Jul 25 '17 at 04:23
  • 1
    Possible duplicate of [How can I flatten lists without splitting strings?](https://stackoverflow.com/questions/5286541/how-can-i-flatten-lists-without-splitting-strings) – McGrady Jul 25 '17 at 04:23
  • Note that this is not a duplicate as it's dealing with strings mixed with lists. – Carolyn Van Spyk Jul 25 '17 at 04:27
  • But the answers to the possible-dupe seem illuminating enough to suggest that this would be a very ugly one-liner. – perigon Jul 25 '17 at 04:28
  • It doesn't also matter that it's unordered, I only need to fetch the values and the order in the inner lists doesn't matter, it will be sorted in the end. – Carolyn Van Spyk Jul 25 '17 at 04:29
  • It is true this will not be a nice one-liner, however, I'm required to produce one. – Carolyn Van Spyk Jul 25 '17 at 04:30

3 Answers3

3

This works, but it's not pretty. If sublist is not a list, it makes it into a one-element list.

[val for sublist in dictionary.values() for val in (sublist if type(sublist) is list else [sublist])]
perigon
  • 2,160
  • 11
  • 16
2

One approach is to normalise all of the values to iterables and use intertools.chain to combine the results eg

from itertools import chain

list(chain(*(v if isinstance(v, list) else (v,) for v in dictionary.values()))

What this does is convert all non-lists into tuples (eg an iterable) then uses chain to combine all the iterables and finally list to provide you with a list.

If you don't want duplicates, use set instead of a list.

Tim
  • 2,510
  • 1
  • 22
  • 26
0

I don't know how useful is this, but, if you insist on having it in compression form try:

[m for n in [[i] for i in dictionary.values() if not list(i)==i ]+[i for i in dictionary.values() if list(i)==i ] for m in n]

you will get:

['one', 'two', 'five', 'three', 'four']
Sohrab Rahimi
  • 215
  • 1
  • 7