python3中sorted用法_Python3 sorted函数中key参数的作用原理

这是一个字符串排序,排序规则:小写

s = 'asdf234GDSdsf23'  #排序:小写-大写-奇数-偶数

print("".join(sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))))

这里key接受的函数返回的是一个元组?是如何进行比较的?

先比较元组的第一个值,FALSE

讓我們從一個簡單的例子開始:

items = [(1, 2), (2, 1)]

print(sorted(items))

結果:

[(1, 2), (2, 1)]

items

是一個 list of tuple,如果針對 tuple 排序,Python 的 Builtin function

sorted

(或是

sort

) 會從 tuple 的最後一個元素開始進行排序,也就是說一組二元素的 tuple 進行排序可以想像成兩次基本的排序:

原本是:

[(2, 1), (1, 2)]

第一次排序以第2個元素為 key,所以排序的結果為:

[(2, 1), (1, 2)]

第二次排序以第1個元素為 key,所以排序的結果為:

[(1, 2), (2, 1)] # 最終結果

結論(1):

tuple 的排序由最後的元素往前依次進行排序

也就是說 tuple 的排序權重是由第一個元素開始依次向後遞減

接著我們來觀察一下 Boolean value 的排序:

print(sorted([True, False])

結果:

[False, True] # False在前,True在後

結論2:

Boolean 的排序會將

False

排在前,

True

排在後

那我們來看看你給出的例子,我們撰寫一個簡單的 function 來觀察結果:

def show(s):

for x in s:

print((x.isdigit(), x.isdigit() and int(x)%2==0, x.isupper(), x.islower(), x))

function

show

會列印出當下的字串

s

用來排序時每個字元所產生的 tuple key.

接著我們套用剛剛的結論1,我們先不使用 tuple 來作為 key,反而利用等價的 由最後一個元素往前依次為 key 排序,並且逐步觀察

s

和 tuple key 的變化:

print('key=x')

s = sorted(s ,key=lambda x: x)

show(s)

print('key=islower()')

s = sorted(s ,key=lambda x: x.islower())

show(s)

print('key=isupper()')

s = sorted(s ,key=lambda x: x.isupper())

show(s)

print('key=isdigit() and int(x)%2==0')

s = sorted(s ,key=lambda x: x.isdigit() and int(x)%2==0)

show(s)

我們將會發現一如預期地,依照結論(1),這樣的做法的確等價於一口氣以 tuple 為 key 來排序.

同時觀察,結論(2),對於

isdigit()

,

isupper()

,

islower()

等所產生的 Boolean key 來說,排序的結果也如預期.

print('key=isdigit()')

s = sorted(s ,key=lambda x: x.isdigit())

show(s)

不過我想這還不是我們最後的結論,因為這是一個碰巧的結果(說碰巧也許太超過了,應該說是不那麼直覺的結果),讓我們根據 結論(1) 對最初的例子進行分析:

sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))

這個排序我們可以翻譯成:

先對字元x本身做排序,接著是對 字元是否為小寫,字元是否為大寫,字元是否為偶數,字元是否為數字分別作排序.

也可以翻譯成:

我們以 字元是否為數字為最高排序權重,接著以字元是否為偶數,字元是否為大寫,字元是否為小寫,字元x本身為權重來做排序.

這似乎與一開始的目標(#排序:小写-大写-奇数-偶数)不同,起碼跟目標沒有直覺上的對應.

建議可以改成:

print("".join(sorted(s1, key=lambda x: (not x.islower(), not x.isupper(), not(x.isdigit() and int(x)%2==1), x))))

這樣就可以解讀為:

我們以 字元是否為小寫為最高權重,接著以字元是否為大寫,字元是否為奇數,字元x本身為權重來做排序

有趣的是:我們想要讓判斷式為

True

的字元在排序完成後在比較前面的位置,所以根據結論(2)加了一個

not

來讓符合的字元可以在前面.

关键之处如

donghui

所说,FALSE

key为元组的排序情况,是每个待排序元素生成一个元组

(x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x)

,排序时是根据这个元组排序,依据是FALSE

测试代码如下:(来源自

dokelung

donghui

)

if __name__ == '__main__':

s = 'asdf234GDSdsf23'

print('key=x')

s = sorted(s, key=lambda x: x)

for x in s:

print((x, x))

print('key=islower()')

s = sorted(s, key=lambda x: x.islower())

for x in s:

print((x.islower(), x))

print('key=isupper()')

s = sorted(s, key=lambda x: x.isupper())

for x in s:

print((x.isupper(), x))

print('key=isdigit() and int(x)%2==0')

s = sorted(s, key=lambda x: x.isdigit() and int(x) % 2 == 0)

for x in s:

print((x.isdigit() and int(x) % 2 == 0, x))

print('key=(x.isupper(), x.islower())')

s = sorted(s, key=lambda x: (x.isupper(), x.islower()))

for x in s:

print((x.isupper(), x.islower(), x))

print('key=(x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))')

s = sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))

for x in s:

print((x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))

运行查看输入可以发现规律。

输出:

key=x

('2', '2')

('2', '2')

('3', '3')

('3', '3')

('4', '4')

('D', 'D')

('G', 'G')

('S', 'S')

('a', 'a')

('d', 'd')

('d', 'd')

('f', 'f')

('f', 'f')

('s', 's')

('s', 's')

key=islower()

(False, '2')

(False, '2')

(False, '3')

(False, '3')

(False, '4')

(False, 'D')

(False, 'G')

(False, 'S')

(True, 'a')

(True, 'd')

(True, 'd')

(True, 'f')

(True, 'f')

(True, 's')

(True, 's')

key=isupper()

(False, '2')

(False, '2')

(False, '3')

(False, '3')

(False, '4')

(False, 'a')

(False, 'd')

(False, 'd')

(False, 'f')

(False, 'f')

(False, 's')

(False, 's')

(True, 'D')

(True, 'G')

(True, 'S')

key=isdigit() and int(x)%2==0

(False, '3')

(False, '3')

(False, 'a')

(False, 'd')

(False, 'd')

(False, 'f')

(False, 'f')

(False, 's')

(False, 's')

(False, 'D')

(False, 'G')

(False, 'S')

(True, '2')

(True, '2')

(True, '4')

key=(x.isupper(), x.islower())

(False, False, '3')

(False, False, '3')

(False, False, '2')

(False, False, '2')

(False, False, '4')

(False, True, 'a')

(False, True, 'd')

(False, True, 'd')

(False, True, 'f')

(False, True, 'f')

(False, True, 's')

(False, True, 's')

(True, False, 'D')

(True, False, 'G')

(True, False, 'S')

key=(x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.isupper(), x.islower(), x))

(False, False, False, True, 'a')

(False, False, False, True, 'd')

(False, False, False, True, 'd')

(False, False, False, True, 'f')

(False, False, False, True, 'f')

(False, False, False, True, 's')

(False, False, False, True, 's')

(False, False, True, False, 'D')

(False, False, True, False, 'G')

(False, False, True, False, 'S')

(True, False, False, False, '3')

(True, False, False, False, '3')

(True, True, False, False, '2')

(True, True, False, False, '2')

(True, True, False, False, '4')

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值