【问题标题】:List of Dictionary Manipulation in python - TypeError: unhashable type: 'dict'python 中的字典操作列表 - TypeError: unhashable type: 'dict'
【发布时间】:2016-10-01 16:11:45
【问题描述】:

我有以下表格的列表:

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}]  

转换成

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}]  

我试过了

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

得到

s = set([d['x'] for d in oldlist])
TypeError: unhashable type: 'dict'

有没有更简单的方法?另外在这里我知道 x 只能有三个值,所以我创建了三个变量 list1、list2 和 list3。如果 x 可以有其他几个值,我必须找到一个类似的字典列表,比如 final!它也应该适用于字符串!

编辑:我试过这个。但这一切都搞砸了

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

【问题讨论】:

  • 如果您可以共享引发错误的行会很有帮助

标签: python


【解决方案1】:

您可以使用defaultdict,其中键是frozenset 从原始字典中的x 值创建的对象,值是相对y 的列表。然后你可以用列表理解构造最终结果并将frozensets转回dicts:

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}]

【讨论】:

  • 谢谢,我知道这会发布!
  • @DeanChristianArmada:另一种选择是将 dict 中的项目转换为元组的元组,但由于 dict 是无序的,因此您需要对它们进行排序。 {'a': 1, 'b': 2}.items() 要么返回 [('a', 1), ('b', 2)] 要么返回 [('b', 2), ('a', 1)]
  • 这也是一个很长的方法。我不知道 python 的集合库
【解决方案2】:

python的set函数不允许字典,不能强求,换个方法试试。 (仔细看看5th6th行的评论)

试试这个代码:

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

【讨论】:

  • 非常感谢!这可行,但我们知道对于 x 在 oldlist 中只有三个不同的值,因此我们可以分配 list1 list2 和 list 3。但如果这是一个意外的数字怎么办!你能推荐点什么吗?
  • 刚刚看到你的评论,请稍等,但你能投票支持我的改变吗?
【解决方案3】:

set函数只能处理hashable对象,如字符串、数字、元组等

List、dict 等数据类型是不可散列的类型,因此 set 函数无法处理它们。

为了更清楚:

What do you mean by hashable in Python?

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

您需要的基本实现:

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']]})

这会给你预期的结果

【讨论】:

  • 那么我可以对我的代码进行哪些更改以使其正常工作?
  • @glitterati:无法为此找出任何特定的算法。必须通过正常的蛮力方法来做
  • 什么是“正常的蛮力方法”?我的好像不行!
猜你喜欢
  • 1970-01-01
  • 2015-11-24
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 2014-10-15
相关资源
最近更新 更多