这个其实就是 Python 的 sorted 方法的使用。
你只要在这句代码
1 | count_pairs = sorted (counter.items(), key = lambda x: ( - x[ 1 ], x[ 0 ]))
|
后面加上类似这样的日志,即可理解:
1 2 3 4 | count_pairs = sorted (counter.items(), key = lambda x: ( - x[ 1 ], x[ 0 ]))
print ( "######### count_pairs BEGIN #########" )
print (count_pairs)
print ( "######### count_pairs END #########" )
|
然后你运行 python train.py, 它会输出:
1 2 3 4 5 6 7 8 9 | [
( 'the' , 50770 ), ( '<unk>' , 45020 ), ( '<eos>' , 42068 ),
( 'N' , 32481 ), ( 'of' , 24400 ), ( 'to' , 23638 ), ( 'a' , 21196 ),
( 'in' , 18000 ), ( 'and' , 17474 ) ...
( 'sim' , 1 ), ( 'snack-food' , 1 ), ( 'ssangyong' , 1 ), ( 'swapo' , 1 ),
( 'wachter' , 1 )
]
|
你可以看到,
1 2 3 | the 这个单词在文本里出现频次最多,有 50770 次
<unk> (表示 unknown(未知))出现第二多,有 45020 次
sim 这个单词的出现频次是最少之一,有 1 次
|
等等。
可以看到这些对(pair)都是按照出现频次降序排列。
因为我们的代码经过 Counter 处理过之后,就从之前的只有单词,变成了 (单词,出现频次数目) 这样一对对的:
1 2 | counter = collections.Counter(data)
|
然后 counter 又被传递给 sorted 方法去进行排序,那么根据什么来进行排序呢?就是这里的 key(关键字)这个参数发挥作用的时候了:
1 | key = lambda x: ( - x[ 1 ], x[ 0 ]))
|
lambda 是一个匿名函数。这里的 x 表示我们给 sorted 方法的输入 counter。优先按照 -x[1] 来排序,如果 -x[1] 相同的情况下,再按照 x[0] 来排序。
你可以看到对于每一个对(pair),例如 ('and', 17474),如果说它是 x,那么它的第一个元素是 x[0],也就是 'and' 这个单词;它的第二个元素是 17474,表示它的出现频次,是 17474 次。
因为如果不加 -x[1] 那个负号,那么就是按照正序排列(从小到大的顺序):1, 2, 3, 4, 5, 6, ... 17474, 18000, 21196, 23638, 24400, 32481, 42068, 45020, 50770
但是加了负号,就变成按照逆序排列了:-50770, -45020, -42068, -32481, -24400, -23638, -21196, -18000, -17474, ... -6, -5, -4, -3, -2, -1
这样就实现了我注释里说的:
然后,因为 x[0] 表示如果在 -x[1] 相同(也就是出现频次数目相同)时,按照单词本身的字典顺序来排列,比如日志里输出的:
1 | ( 'good' , 372 ), ( 'used' , 372 )
|
这两个单词,good 和 used,它们的输出频次都是 372 次,但 good 排在 used 前面,因为在字母顺序里,g 在 u 前面。