簡體   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