Python“;“设置”;具有重复/重复的元素

Python“;“设置”;具有重复/重复的元素,python,collections,dictionary,set,Python,Collections,Dictionary,Set,是否有一种标准方法来表示可能包含重复元素的“集合” my_list = [1, 1, 2, 3, 3, 3] my_list.count(1) # will return 2 class _basebag(Set): """ Base class for bag and frozenbag. Is not mutable and not hashable, so there's no reason to use this instead of either bag

是否有一种标准方法来表示可能包含重复元素的“集合”

my_list = [1, 1, 2, 3, 3, 3]

my_list.count(1) # will return 2
class _basebag(Set):
    """
    Base class for bag and frozenbag.   Is not mutable and not hashable, so there's
    no reason to use this instead of either bag or frozenbag.
    """
    # Basic object methods

    def __init__(self, iterable=None):
        """Create a new basebag.

        If iterable isn't given, is None or is empty then the bag starts empty.
        Otherwise each element from iterable will be added to the bag
        however many times it appears.

        This runs in O(len(iterable))
        """
        self._dict = dict()
        self._size = 0
        if iterable:
            if isinstance(iterable, _basebag):
                for elem, count in iterable._dict.items():
                    self._inc(elem, count)
            else:
                for value in iterable:
                    self._inc(value)
据我所知,一个集合只有一个或零个元素。我想要任何号码

我目前正在使用一个字典,其中元素作为键,数量作为值,但由于许多原因,这似乎是错误的

动机: 我相信有很多这样的收藏申请。例如,对喜爱颜色的调查可以表示为: 调查=[“蓝色”、“红色”、“蓝色”、“绿色”]

在这里,我不关心订单,但我关心数量。我想做以下事情:

survey.add('blue')
# would give survey == ['blue', 'red', 'blue', 'green', 'blue']
…甚至可能

survey.remove('blue')
# would give survey == ['blue', 'red', 'green']
注意事项: 是的,set不是这种集合的正确术语。还有更正确的吗


当然可以列出一份清单,但所需的收集是无序的。更不用说集合的方法命名在我看来更合适。

您使用dict with element/count的方法在我看来似乎还可以。您可能需要更多的功能。看一看

  • O(1)测试元素是否存在以及当前计数检索(比使用列表中的
    元素和
    列表中的
    计数(元素)
    更快)
  • counter.elements()
    看起来像一个包含所有重复项的列表
  • 易于操作与其他计数器的联合/差异

如果您需要副本,请使用列表,并在需要作为集合操作时将其转换为集合。

您可以使用普通的
列表
并在需要访问元素“数量”时使用
列表。计数(元素)

my_list = [1, 1, 2, 3, 3, 3]

my_list.count(1) # will return 2
class _basebag(Set):
    """
    Base class for bag and frozenbag.   Is not mutable and not hashable, so there's
    no reason to use this instead of either bag or frozenbag.
    """
    # Basic object methods

    def __init__(self, iterable=None):
        """Create a new basebag.

        If iterable isn't given, is None or is empty then the bag starts empty.
        Otherwise each element from iterable will be added to the bag
        however many times it appears.

        This runs in O(len(iterable))
        """
        self._dict = dict()
        self._size = 0
        if iterable:
            if isinstance(iterable, _basebag):
                for elem, count in iterable._dict.items():
                    self._inc(elem, count)
            else:
                for value in iterable:
                    self._inc(value)
你在找一个新的工作

Python最接近的数据类型是:

计数器
是用于计算散列对象的
dict
子类。这是一个 无序集合,其中元素存储为字典键和 它们的计数存储为字典值。允许进行计数 任何整数值,包括零或负计数计数器
类 类似于其他语言中的Bag或Multiset。


对于multiset的实际实现,请使用pypi上数据结构包中的类。请注意,这仅适用于Python3。如果您需要Python2,这是为Python2.4编写的
包的配方。

另一种Python multiset实现使用排序列表数据结构。PyPI上有几个实现。一个选项是模块,它实现了一种数据类型,该数据类型有效地实现了类似集合的方法,如
添加
删除
,以及
包含
。sortedcontainers模块采用纯Python、fast-as-C实现(甚至更快),具有100%的单元测试覆盖率和数小时的压力测试

从PyPI安装很容易:

pip install sortedcontainers
如果无法
pip安装
,只需将sortedlist.py文件从

将其作为一个集合使用:

from sortedcontainers import SortedList
survey = SortedList(['blue', 'red', 'blue', 'green']]
survey.add('blue')
print survey.count('blue') # "3"
survey.remove('blue')

sortedcontainers模块还与其他流行的实现保持一致。

您所寻找的实际上是一个(或包),一个不一定是不同元素的集合(而一个集合不包含重复元素)

这里有一个multiset的实现:(Pypy的模块)

多集的数据结构称为
bag
bag
collections
模块中
Set
类的一个子类,带有一个额外的字典来跟踪元素的多样性

my_list = [1, 1, 2, 3, 3, 3]

my_list.count(1) # will return 2
class _basebag(Set):
    """
    Base class for bag and frozenbag.   Is not mutable and not hashable, so there's
    no reason to use this instead of either bag or frozenbag.
    """
    # Basic object methods

    def __init__(self, iterable=None):
        """Create a new basebag.

        If iterable isn't given, is None or is empty then the bag starts empty.
        Otherwise each element from iterable will be added to the bag
        however many times it appears.

        This runs in O(len(iterable))
        """
        self._dict = dict()
        self._size = 0
        if iterable:
            if isinstance(iterable, _basebag):
                for elem, count in iterable._dict.items():
                    self._inc(elem, count)
            else:
                for value in iterable:
                    self._inc(value)
bag
的一个不错的方法是
nlargest
(类似于列表的
计数器
),它返回所有元素的多重性非常快,因为每个元素的出现次数在bag的字典中都是最新的:

>>> b=bag(random.choice(string.ascii_letters) for x in xrange(10))
>>> b.nlargest()
[('p', 2), ('A', 1), ('d', 1), ('m', 1), ('J', 1), ('M', 1), ('l', 1), ('n', 1), ('W', 1)]
>>> Counter(b)
Counter({'p': 2, 'A': 1, 'd': 1, 'm': 1, 'J': 1, 'M': 1, 'l': 1, 'n': 1, 'W': 1}) 
具有重复/重复元素的Python“set”

这取决于如何定义集合。有人可能会认为这是一个错误

  • 顺序无关紧要(无论是有序还是无序)
  • 允许复制/重复元素(又称多重元素)
  • 鉴于这些假设,期权可简化为两种抽象类型:a或a。在Python中,这些类型通常分别转换为
    列表
    计数器
    。请参阅一些需要观察的细节

    给定的

    import random
    
    import collections as ct
    
    random.seed(123)
    
    
    elems = [random.randint(1, 11) for _ in range(10)]
    elems
    # [1, 5, 2, 7, 5, 2, 1, 7, 9, 9]
    
    代码

    复制元素的列表:

    list(elems)
    # [1, 5, 2, 7, 5, 2, 1, 7, 9, 9]
    
    ct.Counter(elems)
    # Counter({1: 2, 5: 2, 2: 2, 7: 2, 9: 2})
    
    复制元素的“多集”:

    list(elems)
    # [1, 5, 2, 7, 5, 2, 1, 7, 9, 9]
    
    ct.Counter(elems)
    # Counter({1: 2, 5: 2, 2: 2, 7: 2, 9: 2})
    

    详细信息

    关于数据结构

    我们这里有很多容易混淆的术语。为了澄清,这里有一些与Python中的数据结构相比的基本数学数据结构

    Type        |Abbr|Order|Replicates|   Math*   |   Python    | Implementation
    ------------|----|-----|----------|-----------|-------------|----------------
    Set         |Set |  n  |     n    | {2  3  1} |  {2, 3, 1}  | set(el)
    Ordered Set |Oset|  y  |     n    | {1, 2, 3} |      -      | list(dict.fromkeys(el)
    Multiset    |Mset|  n  |     y    | [2  1  2] |      -      | <see `mset` below>
    List        |List|  y  |     y    | [1, 2, 2] |  [1, 2, 2]  | list(el)
    
    请注意,存在一些剩余排序,如果您希望得到无序的结果,这可能会令人惊讶。然而,混乱并不妨碍秩序。因此,虽然可以从
    计数器生成多集,但请注意Python中关于剩余排序的以下限制条件:

    • 复制在映射中分组,引入某种程度的顺序
    • 在Python3.6中,dict的保留插入顺序
    摘要

    在Python中,可以将多集转换为多重性映射,即
    计数器
    ,它不像纯集那样随机无序。可能存在一些剩余顺序,这在大多数情况下是可以的,因为顺序在多集合中通常并不重要

    另请参见

    • -关于
      集合中额外数据类型的包
    • N.Wildberger关于数学数据结构的研究

    *在数学上,(根据,我们用括号
    {}
    表示一个集合,用括号
    []
    表示一个列表,如Python所示。与Python不同,逗号
    表示顺序。

    您可以使用
    集合。计数器
    来实现一个多集合,如前所述

    另一种实现多集的方法是使用
    defaultdict
    ,它