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