Python有一个有序字典。那么有序集呢?
当前回答
如果您正在使用有序集来维护有序的顺序,请考虑使用来自PyPI的有序集实现。sortedcontainers模块为此提供了一个SortedSet。一些好处:纯python,像c一样快的实现,100%的单元测试覆盖率,数小时的压力测试。
使用pip从PyPI安装很容易:
pip install sortedcontainers
注意,如果不能pip安装,只需从开源存储库中拉出sortedlist.py和sortedset.py文件。
安装完成后,您可以简单地:
from sortedcontainers import SortedSet
help(SortedSet)
sortedcontainers模块还维护了与几个备选实现的性能比较。
对于询问Python的包数据类型的注释,还有一种SortedList数据类型可用于有效地实现包。
其他回答
我可以为您提供一个比OrderedSet更好的方法:boltons有一个纯python、2/3兼容的IndexedSet类型,它不仅是一个有序集,而且还支持索引(与列表一样)。
简单的pip install boltons(或复制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'
一切都是唯一的,并保持有序。完全披露:IndexedSet是我写的,但这也意味着如果有任何问题,您可以找我麻烦。:)
在Python 2文档中有一个有序集(可能是新的链接)配方。它运行在Py2.6或更高版本和3.0或更高版本上,无需任何修改。该接口几乎与普通的set完全相同,除了初始化应该使用一个列表。
OrderedSet([1, 2, 3])
这是一个MutableSet,所以.union的签名与set的签名不匹配,但由于它包含__or__类似的东西可以很容易地添加:
@staticmethod
def union(*sets):
union = OrderedSet()
union.union(*sets)
return union
def union(self, *sets):
for set in sets:
self |= set
正如其他人所说,OrderedDict在功能方面是有序集的超集,但如果你需要一个与API交互的集,并且不需要它是可变的,OrderedDict.keys()实际上是一个实现abc.collections.Set:
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)
注意事项是不可变性,必须像字典一样构建集合,但它很简单,只使用内置。
在官方库中没有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)
我不知道这种简单的方法是否需要注意,但它解决了我的问题。