[ CodeWar ] - 015:字符串解析统计

234 阅读3分钟

系列文章

题目

img-01

需求:

  • 输入是一个字符串,以一个或多个空格作为分隔符
  • 要求找到字符串中出现数量排名前三的子串
  • 忽略大小写
  • 忽略花里胡哨的符号

解析

这道题的思路比较直接,我们根据需求一步一步来即可:

  • 首先通过 split 分割字符串,由于是以一个或多个空格作为分隔符,所以在分割完成之后,通过 filter 过滤掉空项
  • 通过 map 将字符串转为小写方便比较,通过 replace 替换掉花里胡哨的符号,通过 reduce 统计出每个字符串的数量
  • 通过 sort 以数量进行排序,然后通过 slice 返回排序的前三个即可
function topThreeWords(text{
  let count = 1,
    arr = []
  text
    .split(' ')
    .filter((e) => e)
    .map((s) => s.toLocaleLowerCase().replace(/[^a-zA-Z']/giu''))
    .sort()
    .reduce((pre, cur, i, ar) => {
      if (pre === cur) {
        count += 1
      } else {
        arr.push([pre, count])
        count = 1
      }
      if (i === ar.length - 1) {
        if (pre === cur) {
          count += 1
          arr.push([cur, count])
        } else {
          count = 1
          arr.push([cur, count])
        }
      }
      return cur
    })
  arr = arr
    .sort((a, b) => b[1] - a[1])
    .map((arr) => arr[0])
    .slice(03)
    .filter((e) => e)

  return arr
}

优化

上述代码有好几处可以优化的地方:

  • replace 匹配到数据之后可以直接对匹配到的数据进行操作,所以需要先通过 split 分割字符串
  • 同样,也就不需要 sortfilter 以及 map 对分割后的数组进行统一操作
  • 对于 {key:value} 的格式,JS 中提供了 Map 方法

那么思路可以改成:

  • 通过 replace 匹配到每一个子串,在其回调函数中对子串进行处理
  • 如果 Map 中没有这个 key, 则新增这个 key,否则 keycount + 1
  • 去除 Map 中花里胡哨的符号 key
  • 返回最终数组
const topThreeWords = (text) => {
  let dict = new Map()
  text.replace(/[A-z']+(?=[ ]+|$)/g, (match) => {
    let word = match.toLowerCase()
    dict.set(word, dict.has(word) ? dict.get(word) + 1 : 1)
  })
  dict.delete("'")
  return [...dict]
    .sort((a, b) => b[1] - a[1])
    .map((a) => a[0])
    .slice(03)
}