python3以後不支持cmp,所用key函數並不直接比較任意兩個原始元素,而是經過key函數把那些元素轉換成一個個新的可比較對象,也就是元素的key,而後用元素的key代替元素去參與比較。若是原始元素原本就是可比較對象,好比數字、字符串,那麼不考慮性能優化能夠直接sort(key=lambda e: e)。不過這種基於key函數的設計傾向於每一個元素的大小有個絕對標準,但有時卻會出現單個元素並無一個絕對的大小的狀況,此時可使用 functools.cmp_to_key構建基於多個元素的比較函數。html
以一個leetcode上的題爲例:python
179. 最大數 給定一組非負整數 nums,從新排列每一個數的順序(每一個數不可拆分)使之組成一個最大的整數。 注意:輸出結果可能很是大,因此你須要返回一個字符串而不是整數。 示例 1: 輸入:nums = [10,2] 輸出:"210" 示例 2: 輸入:nums = [3,30,34,5,9] 輸出:"9534330" 示例 3: 輸入:nums = [1] 輸出:"1" 示例 4: 輸入:nums = [10] 輸出:"10" 提示: 1 <= nums.length <= 100 0 <= nums[i] <= 109
能夠看到在這道題中列表nums中兩個值的相對位置並不能由單一num決定,而是說 x與y拼接比y與x拼接的值大,那麼就用[x,y]的順序,不然用[y,x]的順序。此時就是所謂的:單個元素並無一個絕對的大小的狀況性能優化
要解決這道題用sort也很簡單:函數
from functools import cmp_to_key class Solution: def largestNumber(self, nums: List[int]) -> str: nums.sort(key=cmp_to_key(lambda x,y: int(str(y)+str(x)) - int(str(x)+str(y)))) ans = ''.join([str(num) for num in nums]) return str(int(ans))
或者性能
from functools import cmp_to_key def auxComp(x, y): if int(str(x)+str(y)) > int(str(y)+str(x)): return -1 elif int(str(x)+str(y)) < int(str(y)+str(x)): return 1 else: return 0 class Solution: def largestNumber(self, nums: List[int]) -> str: nums.sort(key=cmp_to_key(auxComp)) ans = ''.join([str(num) for num in nums]) return str(int(ans))
至於cmp_to_key中函數的條件能夠這樣理解:優化
sort自己是升序,而題目要求是降序,所以須要cmp_to_key中反着寫(或者加上reverse=True),也就是解法中的:.net
lambda x,y: int(str(y)+str(x)) - int(str(x)+str(y))
以及設計
def auxComp(x, y): if int(str(x)+str(y)) > int(str(y)+str(x)): return -1 elif int(str(x)+str(y)) < int(str(y)+str(x)): return 1 else: return 0
一句話說:python3中一些接受key的函數中(例如sorted,min,max,heapq.nlargest,itertools.groupby),key僅僅支持一個參數,沒法實現兩個參數之間的對比。採用cmp_to_key 函數,能夠接受兩個參數,對兩個參數作處理,好比作和作差,轉換成一個參數,就能夠應用於key關鍵字了。code
參考:orm