Python 统计(词典列表)列表中最常见的列表
我有以下数据结构:Python 统计(词典列表)列表中最常见的列表,python,collections,counter,Python,Collections,Counter,我有以下数据结构: data = [[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}], [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}], [{'Posit': '0'
data = [[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '255', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '0', 'B': '255', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}]]
我想在上面的数据结构中找到最常见的字典列表
我的第一个想法是使用集合中最常见的函数
from collections import Counter
c = Counter()
for point in data:
c[point] += 1
失败,出现类型错误
,因为列表不可损坏
我的下一个想法是将列表转换为元组,因为元组是不可变的
from collections import Counter
c = Counter()
for point in data:
c[tuple(point)] += 1
但后来我得到一个类型错误
,说字典也不易损坏
那么什么是Pythonic方法来实现我想要的呢?您可以使用计数器
,但您必须将列表转换为元组,并将字典转换为元组的排序元组(元组的排序元组键值能够比较两个字典)
As@Marcin正确注释元组(已排序(d.items())
可以被更合适的冻结集(d.items())
替换:
将您的字典转换为元组的冻结集/将它们包装在定义适当的哈希和相等方法的内容中。为了学究式,对于较大的dict,创建冻结集可能会更快(n*k创建时间vs nlogn)。您是指这样的内容吗<代码>计数器(dicts数据中d的元组(frozenset(d.items()))和dicts数据中的元组)。最常见()
>>> Counter(tuple(tuple(sorted(d.items())) for d in a) for a in data).most_common()
[(((('B', '0'), ('G', '255'), ('Posit', '0'), ('R', '0')),
(('B', '0'), ('G', '0'), ('Posit', '1000'), ('R', '255'))),
7),
(((('B', '0'), ('G', '255'), ('Posit', '0'), ('R', '255')),
(('B', '255'), ('G', '0'), ('Posit', '1000'), ('R', '0'))),
1)]
>>> Counter(tuple(frozenset(d.items()) for d in a) for a in data).most_common()
[((frozenset([('Posit', '0'), ('B', '0'), ('G', '255'), ('R', '0')]),
frozenset([('R', '255'), ('G', '0'), ('B', '0'), ('Posit', '1000')])),
7),
((frozenset([('Posit', '0'), ('R', '255'), ('B', '0'), ('G', '255')]),
frozenset([('B', '255'), ('G', '0'), ('R', '0'), ('Posit', '1000')])),
1)]
from collections import namedtuple, Counter
# You can probably think of a better name than this
datum = namedtuple('datum', 'Posit R B G')
Counter(tuple(datum(**d) for d in a) for a in data).most_common()
# You might actually want to make the conversion permanent;
# the data is possibly easier to work with that way given the
# fixed key structure, and it should save memory too