{inner_k: myfunc(inner_v)} isn't a dictionary comprehension. It's just a dictionary.
You're probably looking for something like this instead:
data = {outer_k: {inner_k: myfunc(inner_v) for inner_k, inner_v in outer_v.items()} for outer_k, outer_v in outer_dict.items()}
For the sake of readability, don't nest dictionary comprehensions and list comprehensions too much.
Answer from Blender on Stack Overflow{inner_k: myfunc(inner_v)} isn't a dictionary comprehension. It's just a dictionary.
You're probably looking for something like this instead:
data = {outer_k: {inner_k: myfunc(inner_v) for inner_k, inner_v in outer_v.items()} for outer_k, outer_v in outer_dict.items()}
For the sake of readability, don't nest dictionary comprehensions and list comprehensions too much.
Adding some line-breaks and indentation:
data = {
outer_k: {inner_k: myfunc(inner_v)}
for outer_k, outer_v in outer_dict.items()
for inner_k, inner_v in outer_v.items()
}
... makes it obvious that you actually have a single, "2-dimensional" dict comprehension. What you actually want is probably:
data = {
outer_k: {
inner_k: myfunc(inner_v)
for inner_k, inner_v in outer_v.items()
}
for outer_k, outer_v in outer_dict.items()
}
(which is exactly what Blender suggested in his answer, with added whitespace).
Nested Dictionary Comprehension
How to construct nested dictionary comprehension in Python with correct ordering? - Stack Overflow
python - Nested dictionary comprehension (2 level) - Stack Overflow
dictionary - Python nested dict comprehension - Stack Overflow
What is dictionary comprehension in Python?
Dictionary comprehension is a concise and readable way to create dictionaries in Python. It provides a way to create a new dictionary from an iterable object like a list, tuple, or set.
What is the syntax for dictionary comprehension in Python?
The syntax for dictionary comprehension in Python is as follows: {key:value for (key,value) in iterable}
What are the benefits of using dictionary comprehension in Python?
The benefits of using dictionary comprehension in Python are that it is concise, readable, and reduces the amount of code needed to create dictionaries. It also allows for filtering and transformation of dictionary elements in a single line of code.
I am trying to do a nested dict. comprehension, but running into a syntaxerror.
What I want to do is remove the spaces in my lists. Sorry about the syntax, I had to space it all manually here, it's normal in my code:
email_dict=
{'New ID':
{'Fwd: RES': ['3', ' ', '4', ' ', '5'],
'RES CON': ['2', ' ', '1', '2'],
'RES EXP': [],
'RES SOLD': ['6', ' ', '1', '3']}
}I tried to use this code to loop through each key, and find only the digits / remove the empty spots:
email_dict["New ID"] = {key for key in email_dict["New ID"]:[id for id in email_dict["New ID"][key] if id.isdigit()]}I think I am really close, but not getting something here.
I can make it work when done this way:
for key in email_dict["New ID"]: temp_key = [] for id in email_dict["New ID"][key]: if id.isdigit(): temp_key += id email_dict["New ID"][key] = temp_key
But I'd prefer to learn how to do it a lot cleaner, and without the extra variable.
Note that there is a better way of doing this without a dict comprehension; see below. I’ll first address the issues with your approach.
You need to use nesting order in comprehensions. List your loops in the same order they would be in when nesting a regular loop.
The line.split() expression returns a sequence of two items, but each of those items is not a tuple of a key and a value; instead there is only ever one element being iterated over. Wrap the split in a tuple so you have a 'sequence' of (key, value) items being yielded to assign the two results to two items:
dict2 = {key:value for line in ["1:One", "2:Two", "4:Four"]
for key, value in (line.split(":"),)}
This is the equivalent of:
dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
for key, value in (line.split(":"),):
dict2[key] = value
where the nested loop is only needed because you cannot do:
dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
key, value = line.split(":")
dict2[key] = value
However, in this case, instead of a dictionary comprehension, you should use the dict() constructor. It wants two-element sequences, simplifying the whole operation:
dict2 = dict(line.split(":") for line in ["1:One", "2:Two", "4:Four"])
You can do this a lot simpler with dict and a generator expression:
>>> lst = ["1:One", "2:Two", "4:Four"]
>>> dict(x.split(":") for x in lst)
{'4': 'Four', '1': 'One', '2': 'Two'}
>>>
So you want to play the comprehension game and you want to see a pro player at it.
Forget about itertools, forget about multiple statements. Here is the ultimate comprehension that will make any programmer working on your code throw the keyboard away and leave the room cursing you.
data = {parent_id: {d["name"]: d["id"] for d in [i for i in data if i["parent_id"] == parent_id]} for parent_id in set((j["parent_id"] for j in data))}
But for real though, don't do this in your code if it's going to be shared with someone.
First, sort the list using operator.itemgetter to supply the key:
data.sort(key=itemgetter('parent_id'))
Then use itertools.groupby to group the intended sections in a nested dict-comprehension:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(data, itemgetter('parent_id'))
}
I don't recommend writing a one-liner, but you can do it with sorted:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(sorted(data, key=itemgetter('parent_id')), itemgetter('parent_id'))
}