Python是否有一个有序集?

Python是否有一个有序集?,python,set,Python,Set,Python有一个。那么一个有序的集合呢?有一个(可能的)配方,可以从中引用。它在Py2.6或更高版本和3.0或更高版本上运行,无需任何修改。该接口几乎与普通集合完全相同,只是初始化应该使用列表完成 OrderedSet([1, 2, 3]) 这是一个可变集,因此.union的签名与set的签名不匹配,但由于它包含\uuuuu或\uuuuuu可以轻松添加类似的内容: @staticmethod def union(*sets): union = OrderedSet() uni

Python有一个。那么一个有序的集合呢?

有一个(可能的)配方,可以从中引用。它在Py2.6或更高版本和3.0或更高版本上运行,无需任何修改。该接口几乎与普通集合完全相同,只是初始化应该使用列表完成

OrderedSet([1, 2, 3])
这是一个可变集,因此
.union
的签名与set的签名不匹配,但由于它包含
\uuuuu或\uuuuuu
可以轻松添加类似的内容:

@staticmethod
def union(*sets):
    union = OrderedSet()
    union.union(*sets)
    return union

def union(self, *sets):
    for set in sets:
        self |= set
有序集在功能上是有序字典的特例。 字典的键是唯一的。因此,如果忽略有序字典中的值(例如,通过赋予它们
None
),则基本上是一个有序集

至于Python,则有。以下是OrderedSet的示例实现。(请注意,只需定义或重写少数方法:
collections.OrderedDict
并执行繁重的操作。)

导入集合
类OrderedSet(collections.OrderedDict,collections.MutableSet):
def更新(自我、*args、**kwargs):
如果是kwargs:
raise TypeError(“update()不接受关键字参数”)
对于args中的s:
对于s中的e:
self.add(e)
def添加(自我,要素):
self[elem]=无
def丢弃(自身、要素):
self.pop(元素,无)
定义(自我、其他):
返回全部(e在其他中表示e在自身中)
定义(自身、其他):
返回自我=其他和自我!=其他
定义报告(自我):
返回'OrderedSet([%s])'%(','.join(map(repr,self.keys()))
定义(自我):
返回“{%s}”(,”.join(map(repr,self.keys()))
差异=属性(lambda self:self.\uuuu sub\uuu)
差异\u更新=属性(lambda self:self.\uuuu isub\uuuu)
交叉点=属性(lambda self:self.\uuuu和\uuuu)
交叉点更新=属性(lambda self:self.\uuuuu i和\uuuu)
issubset=属性(lambda self:self.\uuuuu le\uuuu)
issuperset=属性(lambda self:self.\uuuu ge\uuuu)
对称差异=属性(lambda self:self.\uuuuuuxor\uuuuuu)
对称差异更新=属性(lambda self:self.\uuuuuuuixor)
union=属性(lambda self:self.\uuuuuu或\uuuuuu)

对于许多目的,只要调用sorted就足够了。比如说

>>> s = set([0, 1, 2, 99, 4, 40, 3, 20, 24, 100, 60])
>>> sorted(s)
[0, 1, 2, 3, 4, 20, 24, 40, 60, 99, 100]
如果要重复使用此函数,则调用sorted函数会产生开销,因此您可能希望保存结果列表,只要您完成了对集合的更改。如果您需要维护唯一的元素并进行排序,我同意使用OrderedDict from collections的建议,该集合具有任意值,例如None。

PyPI上的实现 虽然其他人已经指出Python中没有内置的插入顺序保持集的实现(但是),但我觉得这个问题缺少一个答案,说明了在这个问题上可以找到什么

这些软件包包括:

  • (基于Python)
  • (基于Cython)
  • (在下,基于Python)
  • (最后更新于2012年)
其中一些实现是基于的,其他答案中也提到了这一点

一些差异
  • 有序集(版本1.1)
  • 优点:O(1)用于按索引进行查找(例如
    my\u集[5]
  • oset(版本0.1.3)
  • 优点:O(1)表示
    删除(项目)
  • 缺点:按索引查找显然是O(n)

两种实现都有O(1),用于<代码>添加(项)< /> >和<>代码>包含(<)项/代码>(< MyLyset 中的代码>项目)。

< P>如果使用有序集来保持排序顺序,请考虑使用来自PyPI的排序SET实现。该模块为此提供了一个新的解决方案。一些好处:纯Python、fast-as-C实现、100%的单元测试覆盖率、数小时的压力测试

使用pip从PyPI安装很容易:

pip install sortedcontainers
请注意,如果无法
pip安装
,只需从中下拉sortedlist.py和sortedset.py文件即可

安装后,您可以简单地:

from sortedcontainers import SortedSet
help(SortedSet)
sortedcontainers模块还维护一个包含多个替代实现的应用程序


对于询问Python的bag数据类型的评论,另外还有一种数据类型可以用来有效地实现bag。

游戏开始有点晚了,但我已经编写了一个类
setlist
,作为
collections extended
的一部分,它完全实现了
Sequence
Set

>>> from collections_extended import setlist
>>> sl = setlist('abracadabra')
>>> sl
setlist(('a', 'b', 'r', 'c', 'd'))
>>> sl[3]
'c'
>>> sl[-1]
'd'
>>> 'r' in sl  # testing for inclusion is fast
True
>>> sl.index('d')  # so is finding the index of an element
4
>>> sl.insert(1, 'd')  # inserting an element already in raises a ValueError
ValueError
>>> sl.index('d')
4
GitHub:

文件:


PyPI:

如果您已经在代码中使用pandas,则其
索引
对象的行为非常类似于有序集,如中所示

文章中的例子:

indA = pd.Index([1, 3, 5, 7, 9])
indB = pd.Index([2, 3, 5, 7, 11])

indA & indB  # intersection
indA | indB  # union
indA - indB  # difference
indA ^ indB  # symmetric difference

我可以做一件比OrderedSet更好的事情:boltons的数据集不仅是一个有序集,而且还支持索引(与列表一样)

只需
pip安装bolton
(或将
setutils.py
复制到您的代码库中),导入
IndexedSet
,然后:

>>> from boltons.setutils import IndexedSet
>>> x = IndexedSet(list(range(4)) + list(range(8)))
>>> x
IndexedSet([0, 1, 2, 3, 4, 5, 6, 7])
>>> x - set(range(2))
IndexedSet([2, 3, 4, 5, 6, 7])
>>> x[-1]
7
>>> fcr = IndexedSet('freecreditreport.com')
>>> ''.join(fcr[:fcr.index('.')])
'frecditpo'

一切都是独一无二的,井然有序。完全披露:我写了
索引集
,但这也意味着:

该包提供了一个有序的集合类,它比基于ActiveState配方的选项更完整。它支持列表可用的所有方法以及集合可用的大多数方法。

官方图书馆中没有
OrderedSet
。 我做了一份详尽的所有数据结构的备忘单,供您参考

DataStructure = {
    'Collections': {
        'Map': [
            ('dict', 'OrderDict', 'defaultdict'),
            ('chainmap', 'types.MappingProxyType')
        ],
        'Set': [('set', 'frozenset'), {'multiset': 'collection.Counter'}]
    },
    'Sequence': {
        'Basic': ['list', 'tuple', 'iterator']
    },
    'Algorithm': {
        'Priority': ['heapq', 'queue.PriorityQueue'],
        'Queue': ['queue.Queue', 'multiprocessing.Queue'],
        'Stack': ['collection.deque', 'queue.LifeQueue']
        },
    'text_sequence': ['str', 'byte', 'bytearray']
}

因此,我也有一个小列表,其中我显然有可能引入非唯一值

我搜索了某种唯一列表的存在性,但随后意识到在添加元素之前测试元素的存在性效果很好

if(not new_element in my_list):
    my_list.append(new_element)

我不知道这个简单的方法是否有注意事项,但它解决了我的问题。

答案是否定的,但您可以使用Python标准库中的键(和v
if(not new_element in my_list):
    my_list.append(new_element)
>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']

>>> list(dict.fromkeys(keywords))
['foo', 'bar', 'baz']
import random
from collections import OrderedDict, abc

a = list(range(0, 100))
random.shuffle(a)

# True
a == list(OrderedDict((i, 0) for i in a).keys())

# True
isinstance(OrderedDict().keys(), abc.Set)