繁体   English   中英

为什么我在 Python 中通过 reduce 对列表进行排序的代码会抛出错误?

[英]Why is my code for sorting a list via reduce in Python throwing an error?

我想到了用 Python 对列表进行排序的单行程序,但没有奏效。 我认为我可以使用reduce来遍历列表并根据需要交换元素,就像冒泡排序一样。 但是今天的解释器令人沮丧:

from functools import  reduce

def reduce_sort(*lst):
    sorter = lambda x, y: y, x if x > y else x, y
    return reduce(sorter, lst)

reduce_sort(5, 4, 6, 7, 1)

这给了我NameError: name 'x' is not defined

有谁知道为什么会这样?

sorter是一个元组:

import ast

print(ast.dump(
  ast.parse("lambda x, y: y, x if x > y else x, y")
))

在线试试吧!

它实际上解析为:

Module(body=[Expr(value=
  Tuple(elts=[
    Lambda(
      args=arguments(posonlyargs=[], args=[arg(arg='x', annotation=None, type_comment=None), arg(arg='y', annotation=None, type_comment=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
      body=Name(id='y', ctx=Load())
    ),
    IfExp(
      test=Compare(left=Name(id='x', ctx=Load()), ops=[Gt()], comparators=[Name(id='y', ctx=Load())]),
      body=Name(id='x', ctx=Load()),
      orelse=Name(id='x', ctx=Load())
    ),
    Name(id='y', ctx=Load())
  ],
ctx=Load()))],type_ignores=[])

所以它相当于

sorter = (lambda x, y: y), (x if x > y else x), y

...其中第二个表达式x if x > y else x将引发异常,因为它不知道x是什么。

您应该明确指定if表达式计算为元组:

sorter = lambda x, y: (y, x) if x > y else (x, y)

现在sorter是一个函数,但整个代码将不起作用,因为在reduce x的第二次迭代中将成为一个元组( if表达式返回的元组之一),将与y进行比较,后者是一个整数. 这样的操作是不可能的,所以你会得到另一个错误,现在在运行时。

使用functools.reduce排序是个好主意。

为什么您的代码目前不起作用

但是,一旦您开始将初始列表中的两个或多个元素组合到一个排序的子列表中,您的函数sorter = lambda x, y: y, x if x > y else x, y不再足够:它只知道如何组合将两个元素放入一个长度为 2 的列表中; 它不知道如何将两个排序列表组合成一个排序列表。

例子:

initial list =   [17, 45, 100, 96, 29, 15, 0, 32, 4, 100, 61, 11, 85, 96, 2, 75, 88, 51, 16, 27, 68, 74, 99, 27, 83, 38, 96, 40, 73, 99, 33, 36, 86, 54, 50, 36, 44, 56, 0, 62, 62, 87, 64, 14, 63, 78, 98, 64, 60, 57, 56, 80, 80, 32, 40, 51, 64, 29, 21, 43, 63, 44, 35, 25, 37, 10, 13, 9, 34, 10, 39, 70, 14, 33, 49, 16, 80, 50, 14, 82, 51, 82, 67, 10, 20, 6, 59, 5, 31, 62, 83, 92, 13, 59, 71, 65, 1, 25, 78, 45]
began reducing = [[17, 45], [96, 100], [15, 29], [0, 32], 4, 100, 61, 11, 85, 96, 2, 75, 88, 51, 16, 27, 68, 74, 99, 27, 83, 38, 96, 40, 73, 99, 33, 36, 86, 54, 50, 36, 44, 56, 0, 62, 62, 87, 64, 14, 63, 78, 98, 64, 60, 57, 56, 80, 80, 32, 40, 51, 64, 29, 21, 43, 63, 44, 35, 25, 37, 10, 13, 9, 34, 10, 39, 70, 14, 33, 49, 16, 80, 50, 14, 82, 51, 82, 67, 10, 20, 6, 59, 5, 31, 62, 83, 92, 13, 59, 71, 65, 1, 25, 78, 45]
sorter([15, 29], [0, 32]) = ???

如何修复此sorter功能? 我们想要的是能够将两个排序列表合并为一个排序列表。 这是否敲响了警钟? 是的! 这是来自mergesortmerge功能。

我们可以自己实现它......或者如果它没有在某处实现,我们可以查看 python 标准模块。 这是。 它被称为heapq.merge

heapq.merge替换sorter

让我们用heapq.merge替换你的sorter

import random
import functools
import heapq
ll = [random.randint(0,100) for i in range(100)]
list(functools.reduce(heapq.merge, ll))
# TypeError: 'int' object is not iterable

哎呀! heapq.merge需要两个可迭代对象。 最初我们的列表不包含列表,它包含单个元素。 我们需要用单例列表或单例元组替换这些单个元素:

import random
import functools
import heapq
ll = [(random.randint(0,100),) for i in range(100)]
list(functools.reduce(heapq.merge, ll))
# [3, 3, 4, 5, 5, 5, 7, 8, 8, 10, 11, 13, 15, 15, 15, 15, 16, 16, 17, 18, 19, 20, 20, 20, 24, 25, 25, 27, 27, 28, 30, 30, 30, 30, 31, 32, 33, 33, 38, 38, 39, 39, 41, 42, 43, 43, 43, 46, 46, 47, 49, 50, 51, 52, 53, 55, 62, 63, 63, 64, 64, 64, 65, 66, 67, 68, 69, 71, 72, 72, 72, 72, 73, 73, 73, 74, 78, 79, 82, 82, 83, 83, 86, 86, 86, 86, 89, 91, 92, 93, 95, 96, 96, 96, 97, 98, 99, 99, 100, 100]

有用! 请注意ll内部的( ,)构造,它生成单例元组。 如果您不喜欢元组并且更喜欢列表,则可以使用[ ]代替( ,)

当然,您希望能够对包含数字而不是单例元组的列表进行排序。 因此,让我们将lambda x: (x,)lambda x: [x]到我们的组合中:

最终的解决方案

import functools
import heapq
def reduce_sort(ll):
  list(functools.reduce(heapq.merge, map(lambda x: (x,), ll)))

import random
ll = [random.randint(0,100) for i in range(100)]
reduce_sort(ll)
# [3, 3, 4, 5, 5, 5, 7, 8, 8, 10, 11, 13, 15, 15, 15, 15, 16, 16, 17, 18, 19, 20, 20, 20, 24, 25, 25, 27, 27, 28, 30, 30, 30, 30, 31, 32, 33, 33, 38, 38, 39, 39, 41, 42, 43, 43, 43, 46, 46, 47, 49, 50, 51, 52, 53, 55, 62, 63, 63, 64, 64, 64, 65, 66, 67, 68, 69, 71, 72, 72, 72, 72, 73, 73, 73, 74, 78, 79, 82, 82, 83, 83, 86, 86, 86, 86, 89, 91, 92, 93, 95, 96, 96, 96, 97, 98, 99, 99, 100, 100]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM