3

I am trying to convert the below to a dict comprehension

my_dict = {'a': None, 'b': None, 'c': ['1', '2', '3']}
new_dict = {}
 for k, v in my_dict.items():
     if not v:
         new_dict[k] = None
     else:
         for item in v:
             new_dict[f'{k}{item}'] = None

I'm trying to translate my dict to

new_dict = {'a': None, 'b': None, 'c1': None, 'c2': None, 'c3': None}

I'm fairly comfortable with basic list and dict comprehensions but struggling with this one, currently looking something like this but clearly I am a bit off on the syntax:

{k: None if not v else f'{k}{item}': None for item in v for k, v in my_dict.items()}
Hemisphere
  • 35
  • 1
  • 4

3 Answers3

7

This abomination will do:

{fk: None
 for k, v in my_dict.items()
 for fk in ([k] if v is None else (k + fv for fv in v))}

If the value is None, you just want the key.
If the value is not None, you want a list of each value concatenated with the key.
Homogenise that to always returning a list, either of one key or multiple:

[k] if v is None else [k + fv for fv in v]

Then you're looking at a "simple" nested comprehension:

{k: None for k in [['a'], ['b'], ['c1', 'c2', 'c3']] for fk in k}
deceze
  • 510,633
  • 85
  • 743
  • 889
0

I was proud of my answer:

new_dict = dict(
    sum(
        [
            [(k, None)] if not value else [(f"{k}{v}", None) for v in value]
            for k, value in my_dict.items()
        ],
        [],
    )
)

... until I saw deceze's answer, which I still need to digest.

Vishal Singh
  • 6,014
  • 2
  • 17
  • 33
Dr. V
  • 1,747
  • 1
  • 11
  • 14
  • Thanks Vishal. your reformatting might help to read the code. My implicit assumption when asked for comprehension is that the code is supposed to be unreadable :-D ... just kidding. – Dr. V Jun 23 '20 at 10:04
0

You can do this with the help of itertools.chain.from_iterable:

>>> {
    y: None
    for y in itertools.chain.from_iterable(
            k if not v else (f"{k}{x}" for x in v) for k, v in my_dict.items()
        )
    }
{'a': None, 'b': None, 'c1': None, 'c2': None, 'c3': None}
CDJB
  • 14,043
  • 5
  • 29
  • 55