按值对 python 集的列表进行排序
Sorting a list of python sets by value
frozenset 文档说:
The frozenset type is immutable and hashable — its contents cannot be altered after it is created; it can therefore be used as a dictionary key or as an element of another set.
但是,python 集的文档说:
Since sets only define partial ordering (subset relationships), the output of the list.sort() method is undefined for lists of sets.
这让我不禁要问:为什么会这样?而且,如果我想按集合内容对集合列表进行排序,我该怎么做?我知道扩展名 intbitset: https://pypi.python.org/pypi/intbitset/2.3.0 具有返回表示设置内容的位序列的功能。 python 集有可比性吗?
元组、列表、字符串等具有自然的字典顺序并且可以排序,因为您始终可以比较给定集合的两个元素。即 a < b
、b < a
或 a == b
.
两个集合之间的自然比较是 a <= b
意味着 a
是 b
的子集,这就是表达式 a <= b
在 [=46 中的实际作用=].文档中 "partial ordering" 的意思是并非所有集合都具有可比性。以以下集合为例:
a = {1, 2, 3}
b = {4, 5, 6}
a
是 b
的子集吗?不是。b
是 a
的子集吗?不,它们相等吗?不,如果你根本无法比较它们,你显然无法对它们进行排序。
您可以对一组集合进行排序的唯一方法是您的比较函数是否真的可以比较任意两个元素 (a total order)。这意味着您仍然可以使用上述子集关系对集合的集合进行排序,但您必须确保所有集合都具有可比性(例如 [{1}, {1, 2, 4}, {1, 2}]
)。
做你想做的最简单的方法是将每个单独的集合转换成你实际上可以比较的东西。基本上,你为一些简单的函数 f
做 f(a) <= f(b)
(其中 <=
很明显)。这是通过 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]
。
举个例子:假设您想按每个集合的 "first element" 对集合列表进行排序。问题是 Python 集或 frozensets 没有 "first element." 它们没有自己的顺序。集合是没有重复元素的无序集合。
此外,list.sort()
对列表进行原位排序,using only the <
operator between items。
如果你只是使用a.sort()
而不传递任何key
参数,说set_a < set_b
(或set_a.__lt__(set_b)
)是不够 .不足之处,我的意思是 set_a.__lt__(set_b)
是一个 subset 运算符。 (a
是 b
的子集吗?)。正如@Blender 提到的和您的问题中提到的,这提供了部分排序而不是全部排序,这不足以定义包含集合的序列。
来自文档:
set < other
: Test whether the set is a proper subset of other, that
is, set <= other
and set != other
.
你 可以 将 key
传递给 sort()
,它不能引用任何与 "ordering" 的在内部设置,因为记住——有 none.
>>> 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}]
frozenset 文档说:
The frozenset type is immutable and hashable — its contents cannot be altered after it is created; it can therefore be used as a dictionary key or as an element of another set.
但是,python 集的文档说:
Since sets only define partial ordering (subset relationships), the output of the list.sort() method is undefined for lists of sets.
这让我不禁要问:为什么会这样?而且,如果我想按集合内容对集合列表进行排序,我该怎么做?我知道扩展名 intbitset: https://pypi.python.org/pypi/intbitset/2.3.0 具有返回表示设置内容的位序列的功能。 python 集有可比性吗?
元组、列表、字符串等具有自然的字典顺序并且可以排序,因为您始终可以比较给定集合的两个元素。即 a < b
、b < a
或 a == b
.
两个集合之间的自然比较是 a <= b
意味着 a
是 b
的子集,这就是表达式 a <= b
在 [=46 中的实际作用=].文档中 "partial ordering" 的意思是并非所有集合都具有可比性。以以下集合为例:
a = {1, 2, 3}
b = {4, 5, 6}
a
是 b
的子集吗?不是。b
是 a
的子集吗?不,它们相等吗?不,如果你根本无法比较它们,你显然无法对它们进行排序。
您可以对一组集合进行排序的唯一方法是您的比较函数是否真的可以比较任意两个元素 (a total order)。这意味着您仍然可以使用上述子集关系对集合的集合进行排序,但您必须确保所有集合都具有可比性(例如 [{1}, {1, 2, 4}, {1, 2}]
)。
做你想做的最简单的方法是将每个单独的集合转换成你实际上可以比较的东西。基本上,你为一些简单的函数 f
做 f(a) <= f(b)
(其中 <=
很明显)。这是通过 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]
。
举个例子:假设您想按每个集合的 "first element" 对集合列表进行排序。问题是 Python 集或 frozensets 没有 "first element." 它们没有自己的顺序。集合是没有重复元素的无序集合。
此外,list.sort()
对列表进行原位排序,using only the <
operator between items。
如果你只是使用a.sort()
而不传递任何key
参数,说set_a < set_b
(或set_a.__lt__(set_b)
)是不够 .不足之处,我的意思是 set_a.__lt__(set_b)
是一个 subset 运算符。 (a
是 b
的子集吗?)。正如@Blender 提到的和您的问题中提到的,这提供了部分排序而不是全部排序,这不足以定义包含集合的序列。
来自文档:
set < other
: Test whether the set is a proper subset of other, that is,set <= other
andset != other
.
你 可以 将 key
传递给 sort()
,它不能引用任何与 "ordering" 的在内部设置,因为记住——有 none.
>>> 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}]