简体   繁体   English

python中的字典操作列表-TypeError:不可哈希类型:'dict'

[英]List of Dictionary Manipulation in python - TypeError: unhashable type: 'dict'

I have a list of the folowing form: 我有以下表格的清单:

oldlist = [{'x': {'a':1,'b':2}, 'y':2},{'x':{'a':6,'b':7}, 'y':2},{'x':{'a':1,'b':2}, 'y':3},{'x':{'a':1,'b':2}, 'y':2},{'x':{'a':10,'b':11}, 'y':4}]  

to be converted into 转换成

final = [{'x':{'a':1,'b':2},'y':[2,3,2],'count':3},{'x':{'a':6,'b':7},'y':[2],'count':1},{'x':{'a':10,'b':11},'y':[4],'count':1}]  

I have tried 我努力了

oldlist = [{'x': {'a':1,'b':2}, 'y':2},{'x':{'a':6,'b':7}, 'y':2},{'x':{'a':1,'b':2}, 'y':3},{'x':{'a':1,'b':2}, 'y':2},{'x':{'a':10,'b':11}, 'y':4}]  
list1=[]  
list2=[]  
list3=[]  
s = set([d['x'] for d in oldlist])  
news=list(s)  
for item in oldlist:  
if item['x'] == news[0]:  
      list1.append(item['y'])  

if item['x'] == news[1]:  
      list2.append(item['y'])  

if item['x'] == news[2]:  
      list3.append(item['y'])  
final=[]  
dic1 = {'x':news[0],'y':list1,'count':len(list1)}  
dic2 = {'x':news[1],'y':list2,'count':len(list2)}  
dic3 = {'x':news[2],'y':list3,'count':len(list3)}  
final.append(dic1)  
final.append(dic2)  
final.append(dic3)  
print final

Getting 得到

s = set([d['x'] for d in oldlist]) s = set([d ['x'] for d in oldlist])
TypeError: unhashable type: 'dict' TypeError:无法散列的类型:'dict'

Is there a simpler way to do it? 有更简单的方法吗? Plus here I knew that x can have only three values so I created three variables list1, list2 and list3. 另外在这里我知道x只能有三个值,所以我创建了三个变量list1,list2和list3。 What if x can have several other values and I have to find out a similar list of dictionaries like final! 如果x可以具有其他几个值,并且我必须找出类似final的字典列表怎么办! It should also work for strings! 它也应该适用于字符串!

EDIT:I tried this. 编辑:我尝试了。 But it all got messed up 但这一切都搞砸了

s = list(frozenset(oldlist[0]['x'].items()))  
print s  
for item in oldlist:  
    s.append(frozenset(item['x'].items()))  

The set function can only handle hashable objects, like a string, number, tuple etc set函数只能处理可hashable对象,例如字符串,数字,元组等

Data types like List, dict are unhashable types, and hence the set function cannot handle them. 像List,dict这样的数据类型是不可散列的类型,因此set函数无法处理它们。

For some more clarity: 为了更加清楚:

What do you mean by hashable in Python? 您在Python中的hashable是什么意思?

http://blog.lerner.co.il/is-it-hashable-fun-and-games-with-hashing-in-python/ http://blog.lerner.co.il/is-it-hashable-fun-and-games-with-hashing-in-python/

A basic implementation of what you need: 您需要的基本实现:

for elem in oldlist:
    found = False
    for item in newlist:
        if elem['x'] == item['x']:
            y = item.get('y',[])
            item['y'] = t.append(elem['y'])
            found = True
            break
    if not found:
        newlist.append({'x':elem['x'], 'y':[elem['y']]})

This will give you the expected result 这将给您预期的结果

Set function of python does not allow dictionaries and you can not force it, try another method instead. python的Set函数不允许使用字典,您不能强制使用它,请尝试其他方法。 (Take a closer look of the comment on the 5th and 6th line) (仔细观察第5行和第6行的评论)

Try this code: 试试这个代码:

oldlist = [{'x': {'a':1,'b':2}, 'y':2},{'x':{'a':6,'b':7}, 'y':2},{'x':{'a':1,'b':2}, 'y':3},{'x':{'a':1,'b':2}, 'y':2},{'x':{'a':10,'b':11}, 'y':4}]  
list1=[]  
list2=[]  
list3=[]  
s = [d['x'] for d in oldlist] # Placed the dictionaries in a list
s = result = [dict(tupleized) for tupleized in set(tuple(item.items()) for item in s)] # This is the manual way on removing duplicates dictionaries in a list instead of using set
news=list(s)  
for item in oldlist:  
    if item['x'] == news[0]:  
        list1.append(item['y'])  

    if item['x'] == news[1]:  
        list2.append(item['y'])  

    if item['x'] == news[2]:  
        list3.append(item['y']) 

final=[]  
dic1 = {'x':news[0],'y':list1,'count':len(list1)}  
dic2 = {'x':news[1],'y':list2,'count':len(list2)}  
dic3 = {'x':news[2],'y':list3,'count':len(list3)}  
final.append(dic1)  
final.append(dic2)  
final.append(dic3)  
print final

You can use defaultdict where keys are frozenset objects created from value of x in the original dicts and values are list of relative y . 您可以使用defaultdict ,其中键是frozenset集合中从x值创建的frozenset对象,而值是相对y列表。 Then you can construct the final result with list comprehension and turn frozensets back to dicts: 然后,您可以使用列表frozensets来构造最终结果,并将frozensets为字典:

from collections import defaultdict

oldlist = [{'x': {'a':1,'b':2}, 'y':2},{'x':{'a':6,'b':7}, 'y':2},{'x':{'a':1,'b':2}, 'y':3},{'x':{'a':1,'b':2}, 'y':2},{'x':{'a':10,'b':11}, 'y':4}]
res = defaultdict(list)
for d in oldlist:
    res[frozenset(d['x'].items())].append(d['y'])

final = [{'x': dict(k), 'y': v, 'count': len(v)} for k, v in res.items()] # [{'y': [2, 3, 2], 'x': {'a': 1, 'b': 2}, 'count': 3}, {'y': [4], 'x': {'a': 10, 'b': 11}, 'count': 1}, {'y': [2], 'x': {'a': 6, 'b': 7}, 'count': 1}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM