作为dict键的无序列表

2024-03-28 11:14:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望能够做到以下几点:

foo = Counter(['bar', 'shoo', 'bar'])
tmp = {}
tmp[foo] = 5

换句话说,是否存在Counter的哈希等价物? 注意,我不能使用frozenset,因为我有重复的元素要保留在键中

编辑: 在我的实际应用程序中,foo中的对象可能无法相互比较,因此无法对列表进行排序


Tags: 对象应用程序元素编辑列表foo排序counter
3条回答

你可以做几件事。一种是对列表进行排序,并将结果转换为tuple。对于小列表来说,这很好

如果有大的列表(包含重复列表),可以将其转换为frozenset,其元素是元组,是(单词,计数)对。例如,如果您的列表是['bar', 'shoo', 'bar'],那么您将有frozenset({('bar', 2), ('shoo', 1)})

您可以通过使用Counter来构造它,或者只需构造一个dictword: count条目,然后将这些条目转换为元组并从中构造一个frozenset

这两个都是可散列的,并且支持原始列表中的重复元素

使用计数器的字符串表示形式

foo = Counter(['bar', 'shoo', 'bar'])
tmp = {}

tmp[str(foo)] = 5

您似乎需要的是一种将无序的密钥数量对用作密钥的方法。一个frozenset可能是一种方法,尽管您必须从Counteritems中创建它,而不是它的keys

foo = Counter(['bar', 'shoo', 'bar'])
tmp = {}
tmp[frozenset(foo.items())] = 5

# tmp: {frozenset({('bar', 2), ('shoo', 1)}): 5}

如果这是令人满意的,您可以通过定义自己的映射类型来实现此转换,如下所示:

from collections import Counter

class CounterDict:
    def __init__(self):
        self.data = {}

    def __setitem__(self, key, value):
        if isinstance(key, Counter):
            self.data[frozenset(key.items())] = value
        else:
            raise TypeError

    def __getitem__(self, key):
        if isinstance(key, Counter):
            return self.data[frozenset(key.items())]
        else:
            raise TypeError

foo = Counter(['bar', 'shoo', 'bar'])
tmp = CounterDict()
tmp[foo] = 42
tmp[foo] # 42

通过使CounterDict成为collections.UserDict的子类,可以使这个实现更加丰富

相关问题 更多 >