Home > Mobile >  Python dictionary comprehension - unhashable type: dict [duplicate]
Python dictionary comprehension - unhashable type: dict [duplicate]

Time:09-30

I need to perform below operations:

  • iterate over a list of dictionary [{},{}]
    • call a transform function which transforms each dictionary, which returns a dictionary.
      • Here key and values are not static, but dataframe name and dataframe value. So dictionary may have one ore more key-value pair.
    • which I would need to store in a final dictionary

Expected : expected data would be a dictionary:

{"key1":"val1", "key2":"val2", "key3":"val3"} # ... in actual, the key would be dataframe name, value would be dataframe value

Simplified Use case:


dictname = [{"key1":"val1","key2":"val2"},{"key3":"value3"}] # input list of dictionary

def transform(each):
    return each # to oversimplify, this would be a dictionary with one or more keys with transformations.

final = {transform(each) for each in dictname}
final

went over other related threads on the issue, could not figure out as how to handle the specific case. Could anyone please guide?e

CodePudding user response:

There are several things wrong in your code.

The dict comprehension is as follows: {key: value, for key, value in something that outputs two things}. In your case transform_each outputs a dict. So fixing this we obtain:

dictname = {"key1":"val1","key2":"val2"} # input dictionary
def transform(each):
    return {each: "new_value"}
final = {key: transform(each) for key,  each in dictname.items()}
final  # {'key1': {'val1': 'new_value'}, 'key2': {'val2': 'new_value'}}

This is not what you want. You need to change only the value of the dict. That is the second thing wrong: Your function must output a value, not a dict. Otherwise, as seen, you got a dict of dicts. You can fix it as follows:

dictname = {"key1":"val1","key2":"val2"} # input dictionary

def transform(each):
    return "new_value"


final = {key: transform(each) for key,  each in dictname.items()}
final  # {'key1': 'new_value', 'key2': 'new_value'

CodePudding user response:

Define transform as

def transform(each):
    return <the new value>

and then use

result = {k: transform(k) for k in dictname}

If you cannot update transform use

from collections import ChainMap
result = dict(ChainMap(*(transform(k) for k in dictname)))

CodePudding user response:

This is an updated answer for the updated question. I think the following should do what you want:

dictname = [{"key1":"val1", "key2":"val2"}, {"key3":"val3"}]

def transform(each):
    return each

final = {k:v for d in dictname for k, v in transform(d).items()}

The transform function takes one of the dictionaries as an argument, and returns a dictionary. The returned dictionaries from all the calls to transform are combined into the top-level dictionary final.

The example above defined final to be:

{'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}

In this example, transform merely returns the dict that was passed to it, but it could return any dict you want.

  • Related