Jacob Myer
Jacob Myer

Reputation: 509

How to create a new dictionary whose keys are those from another dictionary? unhashable type error

I need to make a new dictionary which uses the same keys as the first, while the values of the original have been averaged. So far the values are not giving me trouble but I do not know how to solve the "unhashable type" error. I should mention the original dictionary uses tuples as its keys and values.

studentPerf = 
{('Jeffery','male','junior'):[0.81,0.75,0.74,0.8],
('Able','male','senior'):[0.87,0.79,0.81,0.81],
('Don','male','junior'):[0.82,0.77,0.8,0.8],
('Will','male','senior'):[0.86,0.78,0.77,0.78]}

dictAvgGrade = {studentPerf.keys():[(sum(grade)/4) for grade in studentPerf.values()]}

Upvotes: 2

Views: 163

Answers (4)

Marcos Jota
Marcos Jota

Reputation: 119

According to this

hashable

An object is hashable if it has a hash value which never changes during its lifetime (it needs a hash() method), and can be compared to other objects (it needs an eq() method). Hashable objects which compare equal must have the same hash value.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal, and their hash value is their id().

This means that the key cannot be a list, which is what dict.keys() returns. So you could use dictionary comprehension, like some mentioned before me. That should look like this.

    dictAvgGrade = {key: sum(values)/len(values) for key,values in studentPerf.items()}

And that should do the trick. Hope it helped :)

Upvotes: 1

Kireeti K
Kireeti K

Reputation: 1520

You are getting an unhashable type error because, when you did .keys(), the result would have looked like

{dict_keys([('Jeffery', 'male', 'junior'), ('Able', 'male', 'senior'), ('Don', 'male', 'junior'), ('Will', 'male', 'senior')]): SOMETHING}

Python can't do this as dict_keys is not an acceptable type as a key. Also one more thing to note in your code, is that you tried to do keys and values seperately. Dict don't guarantee order. Even if the code had worked. The order would have messed up.

The right way to do is with items like below

{student: sum(student_marks)/4 for student, student_marks in studentPerf.items()}

Upvotes: 1

martineau
martineau

Reputation: 123501

Your dictionary comprehension is incorrect. Try this:

dictAvgGrade = {key: sum(grades)/len(grades) for key, grades in studentPerf.items()}

Part of the reason you were getting errors was by trying to use studentPerf.keys() as a dictionary key because it's either an iterator in Python 3 or and list in Python 3—neither of which are hashable.

Upvotes: 2

U13-Forward
U13-Forward

Reputation: 71610

Use a dictionary comprehension:

print({k:sum(v)/len(v) for k,v in studentPerf.items()})

Output:

{('Jeffery', 'male', 'junior'): 0.7749999999999999, ('Able', 'male', 'senior'): 0.8200000000000001, ('Don', 'male', 'junior'): 0.7974999999999999, ('Will', 'male', 'senior'): 0.7975000000000001}

Upvotes: 1

Related Questions