力扣 192. 统计词频 解决之道

简介: 力扣 192. 统计词频 解决之道

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情



题目


image.png




问题解决


该题目需要将 words.txt的内容进行统计个数,并且按照降序排序

the day is sunny the

the the sunny is is



方案1


想法

如果能够将文中单词遍历出来,将单词作为key存入map,次数为map的值,这样只需要遍历map不就可以解决该问题了么


实践

要将单词作为key存入map,需要先将单词分割开来

脚本


执行结果

# bash shell_192.sh
the
day
is
sunny
the
the
the
sunny
is
is
#


存入map,并且对结果进行排序

#!/bin/bash
# 定义 map 
declare -A dict
# 遍历数据, 填充 map
while read line
do
        for xx in $line
        do
                dict[$xx]=`expr ${dict[$xx]} + 1`
        done
done < words.txt
# 打印 map 中的数据
for key in ${!dict[*]}
do
        echo -e "$key ${dict[$key]}"
done | sort -k 2 -rn



结果

# bash shell_192.sh
the 4
is 3
sunny 2
day 1
#




方法2


想法

既然上诉我们已经将单词给分割开来了,那么能否用命令uniq去统计次数呢


实践

先对文章单词进行排序

while read line; do for xx in $line; do echo $xx; done; done < words.txt | sort


结果

day
is
is
is
sunny
sunny
the
the
the
the



然后对文章单词进行数据统计(uniq)

while read line; do for xx in $line; do echo $xx; done; done < words.txt | sort | uniq -c


结果

1 day
3 is
2 sunny
4 the


我们的结果是 单词在前 次数在后,所以还需要 awk 进行输出

while read line; do for xx in $line; do echo $xx; done; done < words.txt | sort | uniq -c | awk '{print $2 " " $1}'


结果

day 1
is 3
sunny 2
the 4


然后再对第二行进行排序

while read line; do for xx in $line; do echo $xx; done; done < words.txt | sort | uniq -c | awk '{print $2 " " $1}' | sort -k 2 -rn


结果

the 4
is 3
sunny 2
day 1


能不能将 while read line; do for xx in $line; do echo $xx; done; done < words.txt 转化为命令呢

sed 's# #\n#g' words.txt |  sort | uniq -c | awk '{print $2 " " $1}' | sort -k 2 -rn

但是提交失败了。。。


失败用例


image.png


emmm ,原来有些单词间隔有 多个空格,修改下

在 sed 后面 将 空行 排除掉即可

sed 's# #\n#g' words.txt | grep -v '^$' |  sort | uniq -c | awk '{print $2 " " $1}' | sort -k 2 -rn

再次提交,正常了



方法3


想法

既然 bash 脚本能够编写并且通过测试,那么 使用 awk 脚本,能否可以呢?


使用awk将单词分割开来

gawk '
{
        for (i=1;i<=NF;i++) {
                print ($i)
        }
}' words.txt


结果

the
day
is
sunny
the
the
the
sunny
is
is


使用数组统计次数,和 方案1 的脚本有异曲同工之处,只不过 awk 是放在数组里面

脚本

gawk '
{
        for (i=1;i<=NF;i++) {
                S[$i]=S[$i]+1
        }
}
END {
        for (a in S) {
                print (a,S[a])
        }
}
' words.txt | sort -rn -k 2


结果

the 4
is 3
sunny 2
day 1




技术细节探寻

words.txt 文件为例


对文件进行按行读取


方法1

cat words.txt | while read line
do
  ...
done


方法2

while read line
do
  ...
done < words.txt



方法1 的弊端: 当脚本遇到 管道符 |会开启一个子shell 进行执行,导致的结果是 方法1 中的变量 更改,在循环后就失效了。



bash map

map 和 数组 不同,需要先 申请,在使用

使用 declare -A申请

获取单个map值

${mapName[key]}

获取所有key

${!mapName[@]}

获取所有值

${mapName[@]}

获取map长度

${#mapName[@]}


awk

变量 NF是长度

数组可以直接使用,不用预先申请



其他命令

grep -v '^$'

-v: 取反

'^′:代表以什么开头': ^代表以什么开头 :表以什么开头代表以什么结尾,连接起来则为 空行的意思

uniq -c

-c: 统计次数

sort -k 2 -rn

-k: 以多少行进行排序

-r: 降序排序

-n: 依照数字大小排序




相关文章
|
5月前
|
算法 测试技术 C#
区间合并|LeetCode2963:统计好分割方案的数目
区间合并|LeetCode2963:统计好分割方案的数目
|
5月前
|
算法 安全 测试技术
[组合数学]LeetCode:2954:统计感冒序列的数目
[组合数学]LeetCode:2954:统计感冒序列的数目
|
5月前
|
算法 测试技术 C#
【离散差分】LeetCode2953:统计完全子字符串
【离散差分】LeetCode2953:统计完全子字符串
|
5月前
leetcode-1220:统计元音字母序列的数目
leetcode-1220:统计元音字母序列的数目
47 0
|
5月前
leetcode-1995. 统计特殊四元组
leetcode-1995. 统计特殊四元组
37 0
|
28天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
2月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
40 0
|
3月前
|
存储 算法
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
|
5月前
[leetcode~数位动态规划] 2719. 统计整数数目 hard
[leetcode~数位动态规划] 2719. 统计整数数目 hard
|
5月前
leetcode2376. 统计特殊整数
leetcode2376. 统计特殊整数
50 1