在Python词典列表中使用counter

时间:2016-05-22 14:09:37

标签: python dictionary counter

我正在尝试在字典列表上使用counter来计算每个字典重复的时间。

并非列表中的所有词典都必须具有相同的键。

我假设我有以下列表:

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'

你有什么建议

由于

3 个答案:

答案 0 :(得分:2)

You can't use dictionary as a key in other 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})

答案 1 :(得分:0)

计数器是将项目作为dict存储在iterable中的工具,其中dict.keys()表示项目,dict.values()表示可迭代项目中的项目计数。

但是,在字典中,您不能使用重复键,因为键必须是唯一的。因此,计算任何东西都没有意义,因为我们已经知道它是1.另一方面,dict中可能存在重复的值。例如:

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

现在您可以使用此元组并将其转换为dict

>>> {key: value for key, value in b.items()}
{(25, 'John'): 1, (30, 'John'): 2, (20, 'Jeff'): 1}

或者更进一步,使用collections.namedtuple中的named tuples并按名称标识您的元组,以后您可以更轻松,更清楚地提及这些元组。

希望这会有所帮助。

documentations或此有用set of examples了解有关collections.Counter的详情。您还可以参考YouTube上的Raymond Hettinger(Python的collections工具箱维护者)视频。他有一些关于不同工具的精彩教程。

答案 2 :(得分:0)

不幸的是dict不可以清洗。所以我写了这段代码。结果与您想要的解决方案不同(因为不可能),但您可以使用它。

select set_config('foo.bar', clock_timestamp()::text, false);
...
select current_setting('foo.bar')::timestamp;

此代码返回

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)

ps:抱歉,我的英语很差