在 python 中使用 ord() 和 lambda 排序
Usage of sorted with ord() and lambda in python
我在 Hackerrank 上做了一个练习,在讨论中我偶然发现了一个非常好的单行解决方案来解决以下问题:
S 是一个字母数字字符串,您必须使用以下规则对其进行排序:
- 所有排序的小写字母都在大写字母之前。
- 所有排序的大写字母都在数字之前。
- 所有排序的奇数位都排在排序的偶数位之前。
提供的解决方案是:
print(*sorted(input(), key=lambda c: (-ord(c) >> 5, c in '02468', c)), sep='')
现在,我了解了 lambda 和 ord 的工作原理,我想正确理解这段代码,所以我做了以下工作来理解它:
b = "Sorting1234"
print(*sorted(input(), key=lambda c: (ord(c))), sep='')
输出:
['1', '2', '3', '4', 'S', 'g', 'i', 'n', 'o', 'r', 't']
因此,这段代码根据 ASCII 码对给定的字符串进行排序。现在,我们希望先有小写字母,然后是大写字母,然后是数字,所以我们现在颠倒这个顺序:
sorted(b,key=lambda x: (-ord(x)))
输出:
['t', 'r', 'o', 'n', 'i', 'g', 'S', '4', '3', '2', '1']
现在,这部分我不明白,我们为什么要使用二进制移位运算符,它有什么作用?
sorted(b,key=lambda x: (-ord(x)>>3))
输出:
['r', 't', 'o', 'i', 'n', 'g', 'S', '1', '2', '3', '4']
现在右移 5:
sorted(b,key=lambda x: (-ord(x)>>5))
输出:
['o', 'r', 't', 'i', 'n', 'g', 'S', '1', '2', '3', '4']
我们甚至还没有达到我们实际想要的一半,但完整的代码突然产生了正确的答案:
sorted(b,key=lambda x: (-ord(x)>>5, x in '02467', x))
输出:
['g', 'i', 'n', 'o', 'r', 't', 'S', '1', '3', '2', '4']
看ASCII码table,128个字符排成四列,每列32个(这里只显示printable个字符):
0 32 64 @ 96 `
1 33 ! 65 A 97 a
2 34 " 66 B 98 b
3 35 # 67 C 99 c
4 36 $ 68 D 100 d
5 37 % 69 E 101 e
6 38 & 70 F 102 f
7 39 ' 71 G 103 g
8 40 ( 72 H 104 h
9 41 ) 73 I 105 i
10 42 * 74 J 106 j
11 43 + 75 K 107 k
12 44 , 76 L 108 l
13 45 - 77 M 109 m
14 46 . 78 N 110 n
15 47 / 79 O 111 o
16 48 0 80 P 112 p
17 49 1 81 Q 113 q
18 50 2 82 R 114 r
19 51 3 83 S 115 s
20 52 4 84 T 116 t
21 53 5 85 U 117 u
22 54 6 86 V 118 v
23 55 7 87 W 119 w
24 56 8 88 X 120 x
25 57 9 89 Y 121 y
26 58 : 90 Z 122 z
27 59 ; 91 [ 123 {
28 60 < 92 \ 124 |
29 61 = 93 ] 125 }
30 62 > 94 ^ 126 ~
31 63 ? 95 _ 127
将列编号为 0 到 3,您将在第 1 列中找到数字,在第 2 列中找到大写字母,在第 3 列中找到小写字母。
右移5相当于除以32并向下取整。所以 ord(c) >> 5
会给你列号 1、2 或 3,具体取决于类型 digit/upper/lower。因为我们想要 reversed 顺序,所以我们取反。
实际表达式 -ord(c) >> 5
否定 first(如空格所示),这会稍微改变一下:顶行(代码为 0、32、 64 和 96) 得到错误的列号。但是那些字符与我们无关。
我在 Hackerrank 上做了一个练习,在讨论中我偶然发现了一个非常好的单行解决方案来解决以下问题:
S 是一个字母数字字符串,您必须使用以下规则对其进行排序:
- 所有排序的小写字母都在大写字母之前。
- 所有排序的大写字母都在数字之前。
- 所有排序的奇数位都排在排序的偶数位之前。
提供的解决方案是:
print(*sorted(input(), key=lambda c: (-ord(c) >> 5, c in '02468', c)), sep='')
现在,我了解了 lambda 和 ord 的工作原理,我想正确理解这段代码,所以我做了以下工作来理解它:
b = "Sorting1234"
print(*sorted(input(), key=lambda c: (ord(c))), sep='')
输出:
['1', '2', '3', '4', 'S', 'g', 'i', 'n', 'o', 'r', 't']
因此,这段代码根据 ASCII 码对给定的字符串进行排序。现在,我们希望先有小写字母,然后是大写字母,然后是数字,所以我们现在颠倒这个顺序:
sorted(b,key=lambda x: (-ord(x)))
输出:
['t', 'r', 'o', 'n', 'i', 'g', 'S', '4', '3', '2', '1']
现在,这部分我不明白,我们为什么要使用二进制移位运算符,它有什么作用?
sorted(b,key=lambda x: (-ord(x)>>3))
输出:
['r', 't', 'o', 'i', 'n', 'g', 'S', '1', '2', '3', '4']
现在右移 5:
sorted(b,key=lambda x: (-ord(x)>>5))
输出:
['o', 'r', 't', 'i', 'n', 'g', 'S', '1', '2', '3', '4']
我们甚至还没有达到我们实际想要的一半,但完整的代码突然产生了正确的答案:
sorted(b,key=lambda x: (-ord(x)>>5, x in '02467', x))
输出:
['g', 'i', 'n', 'o', 'r', 't', 'S', '1', '3', '2', '4']
看ASCII码table,128个字符排成四列,每列32个(这里只显示printable个字符):
0 32 64 @ 96 `
1 33 ! 65 A 97 a
2 34 " 66 B 98 b
3 35 # 67 C 99 c
4 36 $ 68 D 100 d
5 37 % 69 E 101 e
6 38 & 70 F 102 f
7 39 ' 71 G 103 g
8 40 ( 72 H 104 h
9 41 ) 73 I 105 i
10 42 * 74 J 106 j
11 43 + 75 K 107 k
12 44 , 76 L 108 l
13 45 - 77 M 109 m
14 46 . 78 N 110 n
15 47 / 79 O 111 o
16 48 0 80 P 112 p
17 49 1 81 Q 113 q
18 50 2 82 R 114 r
19 51 3 83 S 115 s
20 52 4 84 T 116 t
21 53 5 85 U 117 u
22 54 6 86 V 118 v
23 55 7 87 W 119 w
24 56 8 88 X 120 x
25 57 9 89 Y 121 y
26 58 : 90 Z 122 z
27 59 ; 91 [ 123 {
28 60 < 92 \ 124 |
29 61 = 93 ] 125 }
30 62 > 94 ^ 126 ~
31 63 ? 95 _ 127
将列编号为 0 到 3,您将在第 1 列中找到数字,在第 2 列中找到大写字母,在第 3 列中找到小写字母。
右移5相当于除以32并向下取整。所以 ord(c) >> 5
会给你列号 1、2 或 3,具体取决于类型 digit/upper/lower。因为我们想要 reversed 顺序,所以我们取反。
实际表达式 -ord(c) >> 5
否定 first(如空格所示),这会稍微改变一下:顶行(代码为 0、32、 64 和 96) 得到错误的列号。但是那些字符与我们无关。