Lua 第11部分 小插曲:出现频率最高的单词

在本章中,我们要开发一个读取并输出一段文本中出现频率最高的单词的程序。像之前的小插曲一样,本章的程序也十分简单但是也使用了诸如迭代器和匿名函数这样的高级特性。

该程序的主要数据结构是一个记录文本中出现的每一个单词及其出现次数之间关系的表。使用这个数据结构,该程序可以完成 3 个主要任务。

(1)读取文本并计算每一个单词的出现次数。

(2)按照出现次数的降序对单词列表进行排序。

(3)输出有序列表中的前 n 个元素。

要读取文本,可以遍历每一行,然后遍历每一行的每一个单词。对于我们读取的每一个单词,增加对应计数器的值:

Lua 复制代码
local  counter = {}

for line in io.lines() do
	for word in string.gmatch(line, "%w+") do
		counter[word] = (counter[word] or 0) + 1
	end
end

这里,我们使用模式"%w+"来描述"单词", 也就是一个或多个字母或数字。

下一步就是对单词列表进行排序。不过,就像一些有心的读者可能已经注意到的那样,我们并没有可以用来排序的单词列表。尽管如此,使用表 counter 中作为键的单词来创建一个列表还是很简单的:

Lua 复制代码
local words = {}		-- 文本中所有单词的列表

for w in pairs(counter) do
	words[#words + 1] = w
end

一旦有了单词列表,就可以使用函数 table.sort 对其进行排序 :

Lua 复制代码
table.sort( words, function (w1, w2)
	return counter[w1] > counter[w2] or
			counter[w1] == counter[w2] and w1 < w2
end )

统计单词出现频率的程序完整的代码如下:

Lua 复制代码
local  counter = {}

for line in io.lines() do
	for word in string.gmatch(line, "%w+") do
		counter[word] = (counter[word] or 0) + 1
	end
end

local words = {}		-- 文本中所有单词的列表

for w in pairs(counter) do
	words[#words + 1] = w
end

table.sort( words, function (w1, w2)
	return counter[w1] > counter[w2] or
			counter[w1] == counter[w2] and w1 < w2
end )

-- 要输出的字数
local n = math.min(tonumber(arg[1]) or math.huge, #words)

for i = 1, n do
	io.write(words[i], "t", counter[words[i]], "\n")
end

最后一个循环输出了结果,也就是前 n 个单词及它们对应的计数值。这个程序假定第 1个参数是要输出单词的个数;默认情况下,如果没有参数,它会输出所有的单词 。

相关推荐
cici1587416 小时前
基于MATLAB的四旋翼无人机三维动态仿真实例
开发语言·matlab·无人机
m0_7066532316 小时前
高性能网络协议栈
开发语言·c++·算法
永远睡不够的入16 小时前
类和对象(上)
开发语言·c++·算法
想带你从多云到转晴16 小时前
01、JAVAEE--多线程(一)
java·开发语言·javaee
孞㐑¥16 小时前
算法—链表
开发语言·c++·经验分享·笔记·算法
枷锁—sha16 小时前
【CTFshow-pwn系列】06_前置基础【pwn 035】详解:利用 SIGSEGV 信号处理机制
java·开发语言·安全·网络安全·信号处理
学嵌入式的小杨同学16 小时前
【Linux 封神之路】文件操作 + 时间编程实战:从缓冲区到时间格式化全解析
linux·c语言·开发语言·前端·数据库·算法·ux
虾说羊17 小时前
公平锁与非公平锁的区别与不同的使用场景
java·开发语言·spring
瑞雪兆丰年兮17 小时前
[从0开始学Java|第五天]Java数组
java·开发语言
Howrun77717 小时前
C++_bind_可调用对象转化器
开发语言·c++·算法