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

Ben Finney ben+python at benfinney.id.au
Sat Aug 29 23:04:24 EDT 2015


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




More information about the Python-list mailing list