2013-03-13 118 views
3

比方說,我定義列表的lol列表:很難理解lambda函數在排序

lol = [['malasia', 0.02, 56.3], ['chile', 0.03, 34.9], 
     ['hungria', 0.01, 45.9], ['ahumada', 0.001, 1]] 

然後,

lol.sort(lambda x, y: cmp(y[2], x[2])) 

訂單lol每個子列表的最後一個元素...


我只是想了解的組成部分:

  • cmp(y,x)進行比較,以數字,並返回-1(Y以下×),0(x等於y)或1(Y更大的x)的。

  • lambda正在爲每個列表的最後一個元素定義一個函數? 然後lambda裏面排序?我很困惑 - 任何人都可以解釋lambda函數的作用嗎?

+0

的'cmp'參數僅支持向後兼容性。它已從Python3中刪除。總是使用'key ='代替。如果你有一個棘手的情況,其中一個關鍵函數將無法使用'functools.cmp_to_key' helper – 2013-03-13 22:25:27

回答

4

然後lambda裏面排序?我搞不清楚了!

基本上,當sort()需要比較兩個元素,它調用lambda函數並使用它的結果來確定兩個元素應該是第一位的。這就是它的全部。

+2

該OP應該注意,這是非常低效的,因爲它爲每對元素調用一次。改用'key'函數,因爲每個元素只調用一次。 – 2013-03-13 21:38:01

+1

@DanielRoseman:我不明白你的意思。你能詳細說明嗎?就我所理解的而言,關鍵函數總是比較兩個元素,如果另一個元素是在一個自我之前還是之後,還應該如何確定。順便說一下,我認爲timsort是通過key-func在窗簾背後自動工作的,減少了「雙倍」 - 比較,但我從來沒有深入深入。 – 2013-03-13 22:02:04

+0

@DonQuestion''key'函數的意義在於它在每個元素開始排序之前運行一次,並提供一個可用於比較的簡單值。這種排序實際上是對關鍵值進行排序,而不是對元素本身進行排序。將其與'cmp'比較,必須進行每次比較,必須調用cmp函數。 – 2013-03-13 22:11:57

3

這實際上使用key參數更好地完成sort,cmp已經有點過時了。

例如:

lol.sort(key=lambda x: x[2]) 

(你也可以用x [-1]是指列表的最後一個元素)

您所創建的拉姆達並將其傳遞到sort功能。你也可以寫這樣的:

get_third_element = lambda x: x[2] 
lol.sort(key=get_third_element) 

還是要使它更容易理解:

def get_third_element(x): 
    return x[2] 

lol.sort(key=get_third_element) 

沒有理由你不能傳遞一個函數到另一個函數作爲參數!

1

拉姆達的類型是「功能」
所以你

lambda x, y : cmp(y[2], x[2]) 

等於

def f(x, y): 
    return cmp(y[2], x[2]) 

sort需要一個功能,當它需要比較兩個元素,它會調用lambda函數,這將返回值cmp(y[2], x[2])

所以這種排序會排序以這種方式列出:每遇到兩個元素,它將獲取「三元組」中的最後值並比較它們以確定優先級。

1

您示例中的lambda函數確定哪個項目先到達。

在「經典」 -situation它將簡單地計算x-y:如果結果是negative這意味着x is smaller那麼y,並因此來before y

此外,您可能會傳遞一個反向參數到排序方法,這將是reverse=True的順序。

你的「排序」功能在這裏是「lambda-wrapper」中的cmp-function。其中,您將x的順序與y交換,並使用第三個參數,這意味着它按相反的順序排序(x/y-swap),並通過比較所有第三個參數(x[2])來完成。

關於你提到的第2點:

...可能有人解釋拉姆達的功能是什麼」

如果你問一個lambda函數是什麼:它是一個匿名的輕質直列匿名錶示它沒有標識符(但你可以指定一個,例如:sqr = lambda x : x**2,你可以像其他任何函數一樣使用:y = sqr(2)

Normal function: def name(arg): vs lambda-function: lambda arg: ret_value 
       ^^^      ^^^  ^
        a) b) c)       a) b) c)  d) 
  • 一個)關鍵字標記以下作爲在lambda函數的 「丟失」 因此 匿名
  • C)函數參數的情況下,正常/λ-功能
  • B)函數名:正常功能 - >括號,lambda函數 - >不帶
  • d)返回值 - 在省略正常功能的情況下,因爲 必須用返回值顯式返回。 (沒有明確返回它 提供None)lambda隱含地返回冒號右側的 評估的結果。

你的排序函數使用的例子是lambda函數的典型用例。它們被用作「丟棄」功能,你可以在沒有創建自己的正常功能的情況下進行內聯。

更「Python化」的變化會是這樣的:

from operator import itemgetter 

keyfunc = itemgetter(2) # takes the 3rd argument from an itterable 
sorted_list = sorted(lol, key=keyfunc, reverse=True) 
+0

lambda函數與'key'參數無關(不起作用)。它只是定義了一個通用函數對象,而沒有將它與變量相關聯。你可以在與排序完全分開的上下文中使用它。例如,要打印「hello」,可以使用:'(lambda x:print(x))(「hi」)' – 2013-03-14 00:35:38

+0

** a)**返回None不等同於拋出異常。 ** b)**可以編寫與在Python 2.x和3.x中工作的關鍵參數無關的lambda函數,例如。 'lambda x,y:x + y' ** c)**目的是爲了證明lambda函數可以用於與排序完全無關的目的,並且它絕不被稱爲「關鍵函數」。一個特定的lambda函數只是作爲'key'參數傳遞的。 – 2013-03-14 15:37:42

+0

@Asad:順便說一句:我不明白你的假參數:「...關鍵參數(不是函數)」!但是我們在同一頁面上,如果你想從函數中推廣出來,那麼關鍵參數至少應該是可調用的? – 2013-03-14 15:57:03