? ? ? ?在本章中,我們要開發一個讀取并輸出一段文本中出現頻率最高的單詞的程序。像之前的小插曲一樣,本章的程序也十分簡單但是也使用了諸如迭代器和匿名函數這樣的高級特性。
???????該程序的主要數據結構是一個記錄文本中出現的每一個單詞及其出現次數之間關系的表。使用這個數據結構,該程序可以完成 3 個主要任務。
(1)讀取文本并計算每一個單詞的出現次數。
(2)按照出現次數的降序對單詞列表進行排序。
(3)輸出有序列表中的前 n 個元素。
????????要讀取文本,可以遍歷每一行,然后遍歷每一行的每一個單詞。對于我們讀取的每一個單詞,增加對應計數器的值:
local counter = {}for line in io.lines() dofor word in string.gmatch(line, "%w+") docounter[word] = (counter[word] or 0) + 1end
end
這里,我們使用模式"%w+"來描述“單詞”, 也就是一個或多個字母或數字。
????????下一步就是對單詞列表進行排序。不過,就像一些有心的讀者可能已經注意到的那樣,我們并沒有可以用來排序的單詞列表。盡管如此,使用表 counter 中作為鍵的單詞來創建一個列表還是很簡單的:
local words = {} -- 文本中所有單詞的列表for w in pairs(counter) dowords[#words + 1] = w
end
一旦有了單詞列表,就可以使用函數 table.sort 對其進行排序 :
table.sort( words, function (w1, w2)return counter[w1] > counter[w2] orcounter[w1] == counter[w2] and w1 < w2
end )
?統計單詞出現頻率的程序完整的代碼如下:
local counter = {}for line in io.lines() dofor word in string.gmatch(line, "%w+") docounter[word] = (counter[word] or 0) + 1end
endlocal words = {} -- 文本中所有單詞的列表for w in pairs(counter) dowords[#words + 1] = w
endtable.sort( words, function (w1, w2)return counter[w1] > counter[w2] orcounter[w1] == counter[w2] and w1 < w2
end )-- 要輸出的字數
local n = math.min(tonumber(arg[1]) or math.huge, #words)for i = 1, n doio.write(words[i], "t", counter[words[i]], "\n")
end
????????最后一個循環輸出了結果,也就是前 n 個單詞及它們對應的計數值。這個程序假定第 1個參數是要輸出單詞的個數;默認情況下,如果沒有參數,它會輸出所有的單詞 。