Scala实现按分组筛选最大runnumber文件的技术方案咨询
Scala实现:按分组筛选runnumber最大的文件
嘿,这个需求不难搞定,我给你梳理下思路和具体的Scala实现方案:
核心思路
首先得明确怎么从文件名里提取关键信息:
- 把每个文件名按下划线
_拆分,比如vbBaselIIIData_201802_4_d.data.20180405.txt.gz拆分成数组后,索引为2的元素就是runnumber(比如示例里的3、4、4、5)。 - 分组依据是文件名的前两部分拼接(比如
vbBaselIIIData_201802、vbBaselIIIData_201803),同一前缀的文件属于一组。 - 遍历所有文件,对每一组只保留runnumber数值最大的那个文件。
推荐的数据结构
- 先用可变Map(
scala.collection.mutable.Map)临时存储每组的状态:key是分组前缀,value是一个元组(当前最大runnumber, 对应文件名)。这样遍历文件时可以实时更新每组的最大值,效率很高。 - 最终结果存入你需要的可变ListBuffer(
scala.collection.mutable.ListBuffer)。
完整Scala代码实现
import scala.collection.mutable.{ListBuffer, Map} // 模拟目录中的文件列表 val fileNames = List( "vbBaselIIIData_201802_3_d.data.20180405.txt.gz", "vbBaselIIIData_201802_4_d.data.20180405.txt.gz", "vbBaselIIIData_201803_4_d.data.20180405.txt.gz", "vbBaselIIIData_201803_5_d.data.20180405.txt.gz" ) // 临时存储每组的最大runnumber及对应文件 val groupMaxTracker = Map.empty[String, (Int, String)] fileNames.foreach { fileName => val parts = fileName.split("_") // 先校验文件名格式,避免拆分后长度不足导致异常 if (parts.length >= 3 && parts(2).forall(_.isDigit)) { val groupKey = s"${parts(0)}_${parts(1)}" val runNumber = parts(2).toInt groupMaxTracker.get(groupKey) match { case None => // 该组还没有记录,直接存入 groupMaxTracker(groupKey) = (runNumber, fileName) case Some((currentMaxRun, _)) => // 如果当前文件的runnumber更大,更新记录 if (runNumber > currentMaxRun) { groupMaxTracker(groupKey) = (runNumber, fileName) } } } else { // 可选:处理格式不符合的文件,比如打印日志 println(s"跳过格式异常的文件:$fileName") } } // 将结果存入ListBuffer val finalResult = ListBuffer.empty[String] groupMaxTracker.values.foreach { case (_, fileName) => finalResult += fileName } // 验证结果 println("筛选后的文件列表:") println(finalResult.mkString(" "))
代码说明
- 增加了格式校验:检查拆分后的数组长度,以及runnumber是否为纯数字,避免异常文件导致程序崩溃。
- 遍历文件时用Map实时维护每组的最大值,时间复杂度为O(n),处理大量文件时效率也很高。
- 最后从Map中提取所有文件名存入ListBuffer,完全符合你的需求。
内容的提问来源于stack exchange,提问作者OBoy
相关产品推荐
相关产品推荐

