侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

使用Scala处理混合数据集的单词统计

2025-12-14 / 0 评论 / 6 阅读

题目

使用Scala处理混合数据集的单词统计

信息

  • 类型:问答
  • 难度:⭐⭐

考点

Option类型处理,模式匹配,集合操作,函数组合

快速回答

实现步骤:

  1. 使用flatMap过滤None并提取Some中的字符串
  2. 通过flatMap(_.split("\\s+"))拆分单词
  3. map(_.toLowerCase)统一大小写
  4. 使用groupBy(identity)分组后mapValues(_.size)计数
  5. 或使用foldLeftMap.withDefaultValue实现高效计数
## 解析

问题场景

实际开发中常需处理包含空值(None)和有效数据(Some)的混合数据集。本题要求:过滤空值→拆分字符串→统计单词频率(不区分大小写),考察对Scala核心特性的综合应用。

解决方案

def countWords(data: List[Option[String]]): Map[String, Int] = {
  data
    .flatMap(_.toList)          // 过滤None并解包Some
    .flatMap(_.split("\\s+"))   // 拆分单词
    .map(_.toLowerCase)         // 统一小写
    .groupBy(identity)          // 按单词分组
    .mapValues(_.size)          // 计算频次
}

// 替代方案(更高性能)
def countWordsEfficient(data: List[Option[String]]): Map[String, Int] = {
  data.foldLeft(Map.empty[String, Int].withDefaultValue(0)) {
    (acc, option) => option match {
      case Some(str) =>
        str.split("\\s+").foldLeft(acc) { (map, word) =>
          val lower = word.toLowerCase
          map.updated(lower, map(lower) + 1)
        }
      case None => acc  // 跳过空值
    }
  }
}

核心原理

  • Option处理flatMap(_.toList)等价于collect { case Some(s) => s },安全解包避免get的异常风险
  • 模式匹配:在foldLeft中匹配Some/None,符合Scala模式匹配最佳实践
  • 不可变集合Map.updated返回新Map,保证函数式纯特性
  • 正则拆分"\\s+"正则匹配连续空格,避免空字符串

最佳实践

  1. 优先使用Option的转换方法(map/flatMap)而非直接取值
  2. 对大数据集采用foldLeft方案,避免groupBy的中间集合开销
  3. 使用withDefaultValue简化计数逻辑,避免getOrElse重复调用
  4. 单词处理统一转小写,确保统计准确性

常见错误

错误示例后果修正方案
data.map(_.get)遇到None抛出异常改用flatMap(_.toList)
split(" ")无法处理连续空格使用split("\\s+")
未处理大小写"Hello"和"hello"被计为不同单词添加.toLowerCase

扩展知识

  • 性能优化:对于超大数据集,可用groupMapReduce(Scala 2.13+):
    words.groupMapReduce(identity)(_ => 1)(_ + _)
  • 空值处理进阶:结合for-comprehension提升可读性:
    for (opt <- data; s <- opt; word <- s.split("\\s+")) yield word.toLowerCase
  • 并发统计:使用par转换为并行集合加速处理(需注意线程安全)