力扣 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: 依照数字大小排序




相关文章
|
3月前
|
Python
Python|力扣周赛-统计位数为偶数的数字
Python|力扣周赛-统计位数为偶数的数字
38 0
|
3月前
|
算法 程序员
【LeetCode——编程能力入门第一天】基本数据类型[在区间范围内统计奇数数目/去掉最低工资和最高工资后的工资平均值)
给你两个非负整数 low 和 high 。请你返回 low 和 high 之间(包括二者)奇数的数目。 示例 1: 输入:low = 3, high = 7 输出:3 解释:3 到 7 之间奇数数字为 [3,5,7] 。 示例 2: 输入:low = 8, high = 10 输出:1 解释:8 到 10 之间奇数数字为 [9] 。 提示: 0 <= low <= high <= 10^9。
37 0
|
3月前
[leetcode] 828. 统计子串中的唯一字符
[leetcode] 828. 统计子串中的唯一字符
36 0
|
3月前
LeetCode刷题集(七)(2315.统计星号)
LeetCode刷题集(七)(2315.统计星号)
20 0
|
3月前
LeetCode刷题集(一)(LeetCode1684统计一致字符串的数目)
LeetCode刷题集(一)(LeetCode1684统计一致字符串的数目)
26 0
|
4月前
|
Python
Python|Leetcode《1220》|统计元音字母序列的数目
Python|Leetcode《1220》|统计元音字母序列的数目
|
4月前
|
索引 Python
Python|Leetcode《1995》|统计特殊四元组
Python|Leetcode《1995》|统计特殊四元组
|
8月前
LeetCode 1773. 统计匹配检索规则的物品数量
给你一个数组 items ,其中 items[i] = [typei, colori, namei] ,描述第 i 件物品的类型、颜色以及名称。
54 0
|
8月前
LeetCode 1684. 统计一致字符串的数目
给你一个由不同字符组成的字符串 allowed 和一个字符串数组 words 。
39 0
|
8月前
LeetCode 1828. 统计一个圆中点的数目
给你一个数组 points ,其中 points[i] = [xi, yi] ,表示第 i 个点在二维平面上的坐标。多个点可能会有 相同 的坐标。
67 0
相关产品
云迁移中心
推荐文章
更多