osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

TypeError: unhashable type: 'dict' when attempting to hash list - advice sought


kbtyo <ahlusar.ahluwalia at gmail.com> writes:

> I am using Jupyter Notebook and Python 3.4.

Thank you for saying so! It is not always required, but when it matters,
this information is important to state up front.

> I have a data structure in the format, (type list):
>
> [{'AccountNumber': N,
> 'Amount': '0',
>  'Answer': '12:00:00 PM',
>   'ID': None,
>   'Type': 'WriteLetters',
>   'Amount': '10',
>   {'AccountNumber': Y,
>       'Amount': '0',
>       'Answer': ' 12:00:00 PM',       
>        'ID': None,
>       'Type': 'Transfer',
>       'Amount': '2'}]
>
> The end goal is to write this out to CSV.

So that assumes that *every* item will be a mapping with all the same
keys. CSV is limited to a sequence of ?records? which all have the same
fields in the same order.

> The list comprehension "data" is to maintain the integrity of the
> column headers and the values for each new instance of the data
> structure (where the keys in the dictionary are the headers and values
> - row instances). The keys in this specific data structure are meant
> to check if there is a value instance, and if there is not - place an
> ''.
>

[?]
>         for row in results:
>             data = [row.get(index, '') for index in results]

The ?for? statement iterates over ?results?, getting an item each time.
The name ?row? is bound to each item in turn.

Then, each time through the ?for? loop, you iterate *again* over
?results?. The name ?index? is bound to each item.

You then attempt to use the dict (each item from ?results? is itself a
dict) as a key into that same dict. A dict is not a valid key; it is not
a ?hashable type? i.e. a type with a fixed value, that can produce a
hash of the value).

So you're getting dicts and attempting to use those dicts as keys into
dicts. That will give the error ?TypeError: unhashable type: 'dict'?.

I think what you want is not items from the original sequence, but the
keys from the mapping::

    for input_record in results:
        output_record = [input_record.get(key, "") for key in input_record]

But you're then throwing away the constructed list, since you do nothing
with it before the end of the loop.

>         writer.writerow(data)

This statement occurs only *after* all the items from ?results? have
been iterated. You will only have the most recent constructed row.

Perhaps you want::

    for input_record in results:
        output_record = [input_record.get(key, "") for key in input_record]
        writer.writerow(output_record)

-- 
 \       ?An idea isn't responsible for the people who believe in it.? |
  `\                                      ?Donald Robert Perry Marquis |
_o__)                                                                  |
Ben Finney