在Python字典列表中使用计数器

3
我正在尝试在一个字典列表上使用计数器,以便计算每个字典重复出现的次数。列表中并非所有字典都必须具有相同的键。假设我有以下列表:
my_list=({"id":1,"first_name":"Jhon","last_name":"Smith"},{"id":2,"first_name":"Jeff","last_name":"Levi"},{"id":3,"first_name":"Jhon"},{"id":1,"first_name":"Jhon","last_name":"Smith"})

我期望的解决方案是

solution={
 {"id":1,"first_name":"Jhon","last_name":"Smith"}:2
 {"id":2,"first_name":"Jeff","last_name":"Levi"}:1
 {"id":3,"first_name":"Jhon"}}

我尝试过

import collections
c=collections.Counter(my_list)

但是我遇到了以下错误。
TypeError: unhashable type: 'dict'

您有什么建议吗?

谢谢。


1
{d["id"]: d for d in my_list} - khelili miliana
https://wiki.python.org/moin/DictionaryKeys - Dušan Maďar
你不能在另一个字典中使用字典作为键。 - Vedang Mehta
3个回答

5
在其他字典中,您不能使用“dictionary”作为键。这就是为什么会出现“TypeError:unhashable type: 'dict'”的原因。您可以将字典序列化为JSON字符串,然后将其用作字典键。
import json
import collections

my_list = [{"id":1,"first_name":"Jhon","last_name":"Smith"},
           {"id":2,"first_name":"Jeff","last_name":"Levi"},
           {"id":3,"first_name":"Jhon"},
           {"id":1,"first_name":"Jhon","last_name":"Smith"}]

c = collections.Counter(json.dumps(l) for l in my_list)
print c
>>> Counter({'{"first_name": "Jhon", "last_name": "Smith", "id": 1}': 2,
             '{"first_name": "Jeff", "last_name": "Levi", "id": 2}': 1,
             '{"first_name": "Jhon", "id": 3}': 1})

为什么我不能将字典作为另一个字典的键使用? 此外,如果每个元素中没有唯一值,我该怎么办。这意味着我不能指望id不会重复。 - liran_kibo
1
你不能使用任何可变的字典键。因为它的哈希值可能会改变,导致字典映射不正确。 - sparc_spread

0

计数器是一种工具,它将可迭代对象中的项存储为字典,其中dict.keys()表示项,dict.values()表示可迭代对象中该项的计数。

然而,在字典中,您不能有重复的键,因为键必须是唯一的。因此,没有必要计算任何东西,因为我们已经知道它是1。另一方面,字典中可能存储有重复的值。例如:

>>> from collections import Counter  

>>> my_dict = {'a': 'me', 'b':'you', 'c':'me', 'd':'me'} 

>>> Counter(my_dict)  # As plain dict.
Counter({'b': 'you', 'a': 'me', 'c': 'me', 'd': 'me'})

>>> Counter(my_dict.values())  # As dict values. 
Counter({'me': 3, 'you': 1})

现在假设我们有一组字典列表,我们想要计算这些字典中的值;就像你的问题所描述的那样:
>>> my_dict = [
...    {'age': 30, 'name': 'John'}, 
...    {'age': 20, 'name': 'Jeff'}, 
...    {'age': 30, 'name': 'John'}, 
...    {'age': 25, 'name': 'John'}
... ]

>>> Counter(tuple(i.values()) for i in a)  # As a generator of values as tuple.
Counter({(30, 'John'): 2, (25, 'John'): 1, (20, 'Jeff'): 1})

现在你当然可以将这些元组转换成一个字典:
>>> {key: value for key, value in b.items()}
{(25, 'John'): 1, (30, 'John'): 2, (20, 'Jeff'): 1}

或者更进一步,使用来自collections.namedtuplenamed tuples并通过名称标识你的元组,以便以后更轻松、更清晰地引用。

希望这能帮助你。

文档或这个有用的示例集了解更多关于collections.Counter的内容。您还可以参考Raymond Hettinger(Python中collections工具箱的维护者)在YouTube上的视频教程。他有一些非常棒的不同工具的教程。


0

很遗憾,字典是不可哈希的。所以我写了这段代码。结果并不像你想要的解决方案(因为不可能),但也许你可以使用它。

ids_l = [i['id'] for i in my_list]
ids_s = list(set(ids_l))

#k is basickly [id, how many]
k = [[i,ids_l.count(i)] for i in ids_s]

#finding my_list from id
def finder(x):
    for i in my_list:
        if i['id'] == x:
            return i
res = []
for i in range(len(ids_s)):
    #k[i][1] how many value
    #finder(k[i][0]) return dict
    res.append([k[i][1],finder(k[i][0])])
print(res)

这段代码返回

[
    [2, {'id': 1, 'first_name': 'Jhon', 'last_name': 'Smith'}], 
    [1, {'id': 2, 'first_name': 'Jeff', 'last_name': 'Levi'}], 
    [1, {'id': 3, 'first_name': 'Jhon'}]
]

PS:抱歉我的英语不太好


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接