统计词频

标签: None

难度: Medium

写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率

为了简单起见,你可以假设:

  • words.txt只包括小写字母和 ' ' 。
  • 每个单词只由小写字母组成。
  • 单词间由一个或多个空格字符分隔。

示例:

假设 words.txt 内容如下:

the day is sunny the the
the sunny is is

你的脚本应当输出(以词频降序排列):

the 4
is 3
sunny 2
day 1

说明:

  • 不要担心词频相同的单词的排序问题,每个单词出现的频率都是唯一的。
  • 你可以使用一行 Unix pipes 实现吗?

Submission

运行时间: 0 ms

内存: 3.7 MB

# Read from the file words.txt and output the word frequency list to stdout.
cat words.txt | tr -s " " "
" | sort -r | uniq -c | sort -r| awk '{print $2" "$1}'

Explain

该题解使用了Unix管道和一系列命令来统计文本文件中单词的频率。具体步骤如下: 1. 使用`cat`命令读取文件内容 2. 使用`tr`命令将所有空格字符替换为换行符,这样每个单词就会独占一行 3. 使用`sort -r`命令按字典序反向排序所有单词 4. 使用`uniq -c`命令统计每个单词出现的次数,并在每行行首显示频次 5. 使用`sort -r`命令按频次由高到低排序 6. 使用`awk`命令调整输出格式,使其符合题目要求

时间复杂度: 平均情况:O(nlogn),最坏情况:O(n^2)

空间复杂度: O(n)

```bash
# Read from the file words.txt and output the word frequency list to stdout.

# 读取文件内容
cat words.txt | \
# 将空格替换为换行符
tr -s " " "
" | \
# 按字典序反向排序
sort -r | \
# 统计每个单词出现的次数
uniq -c | \
# 按频次由高到低排序 
sort -r | \
# 调整输出格式
awk '{print $2" "$1}'
```

Explore

使用`tr -s " " "\n"`命令将空格替换为换行符的主要好处是可以将每个单词分隔开来,使每个单词单独占据一行。这样做的好处是便于后续的单词计数和排序处理。此外,`tr -s`命令中的`-s`选项会压缩源文本中连续的空格成为一个换行符,这有助于处理文本中可能存在的多余空格,确保单词之间的分隔更为准确。

在进行词频统计之前使用`sort -r`进行字典序反向排序是为了确保相同的单词能够相邻出现,这是因为`uniq -c`命令只能对相邻的重复行进行计数。如果不先排序,相同的单词可能会散布在文件的不同部分,导致`uniq -c`无法正确统计其出现次数。因此,排序是为了数据的正确整理,确保统计的准确性。

`uniq -c`命令通过计算连续重复行的数量来统计频率,因此前提是所有重复的行必须是相邻的。这确实意味着在使用`uniq -c`之前,输入数据必须经过排序,以便所有相同的单词排列在一起。如果没有预先排序,`uniq -c`将无法正确统计分散在文本中的相同单词的出现次数。

虽然`uniq -c`提供了按单词出现频次的部分组织好的数据,但这些数据是按单词的出现顺序而非频次排序的。因此,需要第二次使用`sort -r`来按频次进行排序。如果考虑效率优化,可以考虑使用`sort -nr`,即按数值进行逆序排序,这通常比按文本逆序排序更快,因为它直接对数字进行比较。