python - python中借助闭包函数的排序优先级

标签 python

我读过一本Python教科书,其中有以下与排序结合使用的闭包函数。此排序函数应该首先对属于特殊集的数字进行优先级排序,然后对其余部分进行排序:

def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
        return (1, x)
    values.sort(key=helper)

numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sort_priority(numbers, group)
print(numbers)

输出:

[2, 3, 5, 7, 1, 4, 6, 8]
  1. helper(x)x 参数的实际值在哪里传递?
  2. 据我了解,Python 在元组中首先比较 0 到 0 索引,然后比较 1 到 1 索引等;但不太确定在这种情况下如何使用返回的元组进行比较。

最佳答案

排序键是一个生成替代值供您排序的函数。对替代值进行排序后施加的顺序将强加于原始值。排序键对列表的每个元素应用一次。因此,不要按照指定的顺序进行排序

[8, 3, 1, 2, 5, 4, 7, 6]

您正在按照以下规定的顺序进行排序

[helper(8), helper(3), helper(1), helper(2), helper(5), helper(4), helper(7), helper(6)]

helper对列表中的每个元素调用一次,就像您所做的一样

[helper(x) for x in values]

现在您正在按照以下规定的顺序进行排序

[(1, 8), (0, 3), (1, 1), (0, 2), (0, 5), (1, 4), (0, 7), (1, 6)]

将元素放入元组中可以让您“标记”集合中的元素 {2, 3, 5, 7}带有零,它总是排序在用 1“标记”的元素之前。这是因为“标签”(每个元组的第一个元素)首先被比较。

当键排序时,实际值按相同的顺序放置。

较新版本的 Python 根本不支持比较器,这与 C 和 Java 不同,例如:它根本没有必要。正确构造的键函数可以执行比较器可以执行的所有操作,并且只需要对每个元素求值一次,而不是多次。当然, key 本身仍然需要进行相同次数的比较。

排序键还允许您对没有自然排序的元素列表进行排序(不支持像 < 这样的比较运算符)。使用正确的键,您甚至可以对包含通常无法相互比较的不同类型元素的列表进行排序。

顺便说一句, bool 值是 Python 中整数的特殊子类:False == 0True == 1 。由于这些是您用来将键分成类别的标签,因此您可以重写 helper避免条件:

def helper(x):
    return (x not in group, x)

附录

为了帮助您更好地理解键排序,这里有一个实现,它的作用与将键传递给sort有效地相同。方法,但不是就地(所以更像 sorted 内置):

def my_sorted(iterable, key):
    iterable = list(iterable)
    elements = [(key, index) for index, key in enumerate(iterable)]
    elements.sort()
    return [iterable[index] for _, index in elements]

这会执行以下操作:

  1. 将输入转换为可索引的内容(序列),因为并非所有可迭代对象都可以开箱即用地进行索引。
  2. 计算每个元素的键以及原始列表中的索引。对键进行排序后,这将允许您将元素提取到正确的顺序。它还为排序提供了额外的稳定性。 Python 的默认 Timsort 已经稳定,但键之间的任何联系都将被索引打破。
  3. 按键对键和索引列表进行排序。
  4. 从原始序列中提取每个已排序元素对应的元素,并返回结果。

关于python - python中借助闭包函数的排序优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52472419/

相关文章:

python - Django 使用 Widget 覆盖 ModelForm 属性

python - 如何使 python .post() 请求重试?

python - 如何将 os.walk 的输出写入文件

javascript - selenium phantomjs 无法抓取网站机器人检测

python - Pydev 有选择地运行单元测试

python - 在 Seaborn JointGrid 中向边缘添加 yticks

python - 修复 native Cygwin Vim Python 支持

python - matplotlib 示例代码抛出 TclError

python - 删除 Pandas DataFrame 中值不是 NaN 的所有行

python - 无法为 `pip` 安装 `python 3.3` 但对于 `python 2.7` 工作正常