1

freezeset 文档说:

freezeset 类型是不可变和可散列的——它的内容在创建后不能更改;因此,它可以用作字典键或另一个集合的元素。

但是,python 集的文档说:

由于集合仅定义部分排序(子集关系),因此 list.sort() 方法的输出对于集合列表是未定义的。

这让我不禁要问:为什么会这样?而且,如果我想按集合内容对集合列表进行排序,我该怎么做?我知道扩展 intbitset: https://pypi.python.org/pypi/intbitset/2.3.0具有返回表示设置内容的位序列的功能。python集有可比性吗?

4

2 回答 2

3

元组、列表、字符串等具有自然的字典顺序并且可以排序,因为您始终可以比较给定集合的两个元素。也就是说,要么a < bb < a,要么a == b

两个集合之间的自然比较是让a <= b均值a是 的子集b,这就是表达式a <= b在 Python 中的实际作用。文档中的“部分排序”意味着并非所有集合都具有可比性。以以下集合为例:

a = {1, 2, 3}
b = {4, 5, 6}

a的子集b吗?不,是b的子集a吗?不,他们是平等的吗?不,如果您根本无法比较它们,那么您显然无法对它们进行排序。

您可以对集合进行排序的唯一方法是您的比较函数实际上可以比较任何两个元素(总顺序)。这意味着您仍然可以使用上述子集关系对集合集合进行排序,但您必须确保所有集合都是可比较的(例如[{1}, {1, 2, 4}, {1, 2}])。

做你想做的最简单的方法是将每个单独的集合转换成你实际可以比较的东西。基本上,对于一些简单的功能,您会这样做f(a) <= f(b)<=很明显)f。这是通过key关键字参数完成的:

In [10]: def f(some_set):
   ...       return max(some_set)
   ...

In [11]: sorted([{1, 2, 3, 999}, {4, 5, 6}, {7, 8, 9}], key=f)
Out[11]: [{4, 5, 6}, {7, 8, 9}, {1, 2, 3, 999}]

您正在排序[f(set1), f(set2), f(set3)]并将生成的排序应用于[set1, set2, set3].

于 2018-03-04T03:19:27.677 回答
3

举个例子:假设您想按每个集合的“第一个元素”对集合列表进行排序。问题是 Python 集或冻结集没有“第一个元素”。他们没有自己的秩序感。集合是没有重复元素的无序集合。

此外,仅使用items 之间的运算符list.sort()对列表进行排序。<

如果你只是使用a.sort()而不传递任何key参数,说set_a < set_b(or set_a.__lt__(set_b)) 是不够的。不足,我的意思是这set_a.__lt__(set_b)是一个子集运算符。(是a的子集b?)。正如@Blender 提到的并在您的问题中引用的那样,这提供了部分而不是全部排序,这不足以定义任何序列包含集合。

从文档:

set < other: 检验该集合是否是其他的真子集,即set <= otherset != other

可以将 a 传递keysort(),它只是不能引用与内部集合的“排序”有关的任何内容,因为请记住——没有。

>>> a = {2, 3, 1}
>>> b = {6, 9, 0, 1}
>>> c = {0}
>>> i = [b, a, c]
>>> i.sort(key=len)
>>> i
[{0}, {1, 2, 3}, {0, 9, 6, 1}]
于 2018-03-04T03:21:30.170 回答