Spark-Scala:如何比较不同长度字符串中的日期并返回最小值
Scala处理用户记录提取最小日期实现方案
你原有代码的问题主要有两个:
str_split变量定义在if代码块内部,外部无法访问,会报变量未定义错误- 拆分后只取了前两个元素,没有处理后续动态数量的用户记录
完整实现代码
假设输入行格式示例:user123,login|2022-03-10,pay|2022-01-05,signin|2022-02-20,日期格式为yyyy-MM-dd:
import java.time.LocalDate import java.time.format.DateTimeFormatter // 可根据实际日期格式修改规则 private val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") val extractUserMinDate = (line: String) => { // 处理空输入 if (line == null || line.trim.isEmpty) (null, null) else { val lineParts = line.split(",") val userId = lineParts.head // 跳过第一个userid元素,处理所有后续记录 val minDate = lineParts.tail .filter(record => record.contains("|")) // 过滤格式错误的无效记录 .map(_.split("\\|", 2)(1).trim) // 拆分每条记录取日期部分,加limit=2避免日期内有|的情况 .filter(dateStr => // 可选:加日期格式校验,避免非法日期 try { LocalDate.parse(dateStr, dateFormatter) true } catch { case _: Exception => false } ) .minOption // 兼容无合法日期的场景,不会抛出空集合异常 .getOrElse(null) (userId, minDate) } }
关键逻辑说明
- 用
lineParts.tail获取userid之外的所有用户记录,不管记录条数多少都能自适应处理 - 标准
yyyy-MM-dd格式的日期字符串字典序和时间顺序完全一致,不需要转日期类型也可以直接比较,有特殊格式需求的话可以转成LocalDate后再取最小值 - 加了格式校验、空值兼容逻辑,避免脏数据导致任务报错
如果是在Spark环境中使用,可以直接把这个函数注册为UDF调用:
import org.apache.spark.sql.functions.udf val extractMinDateUdf = udf(extractUserMinDate) // 调用示例:df.select(extractMinDateUdf($"raw_line").as("user_min_date"))
内容的提问来源于stack exchange,提问作者PixieDev
相关产品推荐
相关产品推荐

