Python有一个有序字典。那么有序集呢?
当前回答
正如其他答案所提到的,对于python 3.7+,字典是按定义排序的。我们可以继承abc.collections.MutableSet或typing,而不是继承OrderedDict。MutableSet使用字典的键来存储我们的值。
import itertools
import typing
T = typing.TypeVar("T")
class OrderedSet(typing.MutableSet[T]):
"""A set that preserves insertion order by internally using a dict."""
def __init__(self, iterable: typing.Iterator[T]):
self._d = dict.fromkeys(iterable)
def add(self, x: T) -> None:
self._d[x] = None
def discard(self, x: T) -> None:
self._d.pop(x, None)
def __contains__(self, x: object) -> bool:
return self._d.__contains__(x)
def __len__(self) -> int:
return self._d.__len__()
def __iter__(self) -> typing.Iterator[T]:
return self._d.__iter__()
def __str__(self):
return f"{{{', '.join(str(i) for i in self)}}}"
def __repr__(self):
return f"<OrderedSet {self}>"
然后:
x = OrderedSet([1, 2, -1, "bar"])
x.add(0)
assert list(x) == [1, 2, -1, "bar", 0]
我在一个小库中添加了这些代码和一些测试,所以任何人都可以安装它。
其他回答
正如其他答案所提到的,对于python 3.7+,字典是按定义排序的。我们可以继承abc.collections.MutableSet或typing,而不是继承OrderedDict。MutableSet使用字典的键来存储我们的值。
import itertools
import typing
T = typing.TypeVar("T")
class OrderedSet(typing.MutableSet[T]):
"""A set that preserves insertion order by internally using a dict."""
def __init__(self, iterable: typing.Iterator[T]):
self._d = dict.fromkeys(iterable)
def add(self, x: T) -> None:
self._d[x] = None
def discard(self, x: T) -> None:
self._d.pop(x, None)
def __contains__(self, x: object) -> bool:
return self._d.__contains__(x)
def __len__(self) -> int:
return self._d.__len__()
def __iter__(self) -> typing.Iterator[T]:
return self._d.__iter__()
def __str__(self):
return f"{{{', '.join(str(i) for i in self)}}}"
def __repr__(self):
return f"<OrderedSet {self}>"
然后:
x = OrderedSet([1, 2, -1, "bar"])
x.add(0)
assert list(x) == [1, 2, -1, "bar", 0]
我在一个小库中添加了这些代码和一些测试,所以任何人都可以安装它。
对于许多目的来说,简单地调用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]
如果你要重复使用它,调用排序函数会产生开销,所以你可能想要保存结果列表,只要你完成了对集合的更改。如果您需要维护唯一的元素并进行排序,我同意从具有任意值(如None)的集合中使用OrderedDict的建议。
有一个pip库是这样做的:
pip install ordered-set
然后你可以使用它:
from ordered_set import OrderedSet
正如其他人所说,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)
注意事项是不可变性,必须像字典一样构建集合,但它很简单,只使用内置。
PyPI上的实现
虽然其他人指出Python中还没有插入顺序保留集的内置实现,但我觉得这个问题缺少一个答案,它说明了在PyPI上可以找到什么。
这些是套餐:
有序集(基于Python) orderedset(基于Cython) collections-extended 波顿(在iterutils下。IndexedSet面向) Oset(最后更新于2012年)
其中一些实现是基于Raymond Hettinger发布到ActiveState的配方,在这里的其他回答中也提到了这个配方。
一些差异
有序集(版本1.1) 优点:O(1)用于索引查找(例如my_set[5]) Oset(版本0.1.3) 优点:O(1)用于移除(物品) 缺点:显然O(n)用于索引查找
这两个实现都有O(1)用于add(item)和__contains__(item) (my_set中的项目)。
推荐文章
- 如何读取文件的前N行?
- 如何删除matplotlib中的顶部和右侧轴?
- 解析.py文件,读取AST,修改它,然后写回修改后的源代码
- Visual Studio Code:如何调试Python脚本的参数
- 使用元组/列表等等。从输入vs直接引用类型如list/tuple/etc
- 结合conda环境。Yml和PIP requirements.txt
- 将命名元组转换为字典
- 如何使x轴和y轴的刻度相等呢?
- Numpy在这里函数多个条件
- 在Python中,使用argparse只允许正整数
- 如何排序mongodb与pymongo
- 不可变与可变类型
- 列表是线程安全的吗?
- 操作系统。makdirs在我的路径上不理解“~”
- 如何在Django模板中获得我的网站的域名?