找到最大值 w.r.t。每组格式化字符串中的子字符串
Find maximum w.r.t. substring within each group of formatted strings
我正在努力为某个场景寻找解决方案。我的目录中只有几个文件。让我们说
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。我必须只选择具有最新运行号的文件。所以在这种情况下,我只需要从四个文件中选择两个并将其放入一个可变的 Scala 列表中。 ListBuffer 应包含:
vbBaselIIIData_201802_4_d.data.20180405.txt.gz
vbBaselIIIData_201803_5_d.data.20180405.txt.gz
任何人都可以建议我如何实现它。我正在使用 Scala,但也只有算法值得赞赏。我们可以使用哪些正确的数据结构集?我们需要实现哪些功能?任何建议。
如果您有文件名列表,例如:
val list = 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")
那么你可以这样做:
list.map{f =>
val s = f.split("_").toList
(s(1), f)
}.groupBy(_._1)
.map(_._2.max)
.values
这个returns:
MapLike.DefaultValuesIterable(vbBaselIIIData_201803_5_d.data.20180405.txt.gz, vbBaselIIIData_201802_4_d.data.20180405.txt.gz)
如你所愿。
这是一个很有希望的鼓舞人心的提议,它展示了集合的一大堆不同的语言特性和有用的方法:
val list = 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"
)
val P = """[^_]+_(\d+)_(\d+)_.*""".r
val latest = list
.map { str => {val P(id, run) = str; (str, id, run.toInt) }}
.groupBy(_._2) // group by id
.mapValues(_.maxBy(_._3)._1) // find the last run for each id
.values // throw away the id
.toList
.sorted // restore ordering, mostly for cosmetic purposes
latest foreach println
对您在阅读 Scala 简介时可能忽略的并非完全无关紧要的部分的简要说明:
"regex pattern".r
将字符串转换为已编译的正则表达式模式
- 块
{ stmt1 ; stmt2 ; stmt3 ; ... ; stmtN; result }
计算最后一个表达式 result
- 提取器语法可用于已编译的正则表达式模式
val P(id, run) = str
匹配第二个和第三个 _
分隔值
_.maxBy(_._3)._1
找到具有最高 运行 编号的三元组,然后再次提取第一个组件 str
输出:
vbBaselIIIData_201802_4_d.data.20180405.txt.gz
vbBaselIIIData_201803_5_d.data.20180405.txt.gz
不清楚您有什么性能需求,即使您提到 'algorithm'。
如果您没有更具体的需求,使用 Scala 的 Collection API 可以很容易地做到这一点。即使您正在处理巨大的目录,您也可以通过迁移到 Streams 来获得一些良好的性能特征(至少在内存使用方面)。
所以假设你有一个类似 def getFilesFromDir(path: String): List[String]
的函数,其中 List[String]
是一个文件名列表,你需要执行以下操作:
- 按日期分组文件(
List[String] => Map[String, List[String]]
- 提取 Runnumbers,保留原始文件名 (
List[String] => List[(String, Int)]
)
- Select 最大运行数 (
List[(String, Int)] => (String, Int)
)
- 仅映射到文件名 (
(String, Int) => String
)
- Select 只是结果映射的值 (
Map[Date, String] => String
)
(注意:如果你想走纯函数路线,你需要一个类似def getFilesFromDir(path: String): IO[List[String]]
)
的函数
使用 Scala 的 Collections API 你可以通过这样的方式实现上述目标:
def extractDate(fileName: String): String = ???
def extractRunnumber(fileName: String): String = ???
def getLatestRunnumbersFromDir(path: String): List[String] =
getFilesFromDir(path)
.groupBy(extractDate) // List[String] => Map[String, List[String]]
.mapValues(selectMaxRunnumber) // Map[String, List[String]] => Map[String, String]
.values // Map[String, String] => List[String]
def selectMaxRunnumber(fileNames: List[String]): String =
fileNames.map(f => f -> extractRunnumber(f))
.maxBy(p => p._2)
._1
我将 extractDate
和 extractRunnumber
实现留空。这些可以使用简单的正则表达式来完成 - 如果您遇到问题,请告诉我。
我正在努力为某个场景寻找解决方案。我的目录中只有几个文件。让我们说
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。我必须只选择具有最新运行号的文件。所以在这种情况下,我只需要从四个文件中选择两个并将其放入一个可变的 Scala 列表中。 ListBuffer 应包含:
vbBaselIIIData_201802_4_d.data.20180405.txt.gz
vbBaselIIIData_201803_5_d.data.20180405.txt.gz
任何人都可以建议我如何实现它。我正在使用 Scala,但也只有算法值得赞赏。我们可以使用哪些正确的数据结构集?我们需要实现哪些功能?任何建议。
如果您有文件名列表,例如:
val list = 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")
那么你可以这样做:
list.map{f =>
val s = f.split("_").toList
(s(1), f)
}.groupBy(_._1)
.map(_._2.max)
.values
这个returns:
MapLike.DefaultValuesIterable(vbBaselIIIData_201803_5_d.data.20180405.txt.gz, vbBaselIIIData_201802_4_d.data.20180405.txt.gz)
如你所愿。
这是一个很有希望的鼓舞人心的提议,它展示了集合的一大堆不同的语言特性和有用的方法:
val list = 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"
)
val P = """[^_]+_(\d+)_(\d+)_.*""".r
val latest = list
.map { str => {val P(id, run) = str; (str, id, run.toInt) }}
.groupBy(_._2) // group by id
.mapValues(_.maxBy(_._3)._1) // find the last run for each id
.values // throw away the id
.toList
.sorted // restore ordering, mostly for cosmetic purposes
latest foreach println
对您在阅读 Scala 简介时可能忽略的并非完全无关紧要的部分的简要说明:
"regex pattern".r
将字符串转换为已编译的正则表达式模式- 块
{ stmt1 ; stmt2 ; stmt3 ; ... ; stmtN; result }
计算最后一个表达式result
- 提取器语法可用于已编译的正则表达式模式
val P(id, run) = str
匹配第二个和第三个_
分隔值_.maxBy(_._3)._1
找到具有最高 运行 编号的三元组,然后再次提取第一个组件str
输出:
vbBaselIIIData_201802_4_d.data.20180405.txt.gz
vbBaselIIIData_201803_5_d.data.20180405.txt.gz
不清楚您有什么性能需求,即使您提到 'algorithm'。
如果您没有更具体的需求,使用 Scala 的 Collection API 可以很容易地做到这一点。即使您正在处理巨大的目录,您也可以通过迁移到 Streams 来获得一些良好的性能特征(至少在内存使用方面)。
所以假设你有一个类似 def getFilesFromDir(path: String): List[String]
的函数,其中 List[String]
是一个文件名列表,你需要执行以下操作:
- 按日期分组文件(
List[String] => Map[String, List[String]]
- 提取 Runnumbers,保留原始文件名 (
List[String] => List[(String, Int)]
) - Select 最大运行数 (
List[(String, Int)] => (String, Int)
) - 仅映射到文件名 (
(String, Int) => String
) - Select 只是结果映射的值 (
Map[Date, String] => String
)
(注意:如果你想走纯函数路线,你需要一个类似def getFilesFromDir(path: String): IO[List[String]]
)
使用 Scala 的 Collections API 你可以通过这样的方式实现上述目标:
def extractDate(fileName: String): String = ???
def extractRunnumber(fileName: String): String = ???
def getLatestRunnumbersFromDir(path: String): List[String] =
getFilesFromDir(path)
.groupBy(extractDate) // List[String] => Map[String, List[String]]
.mapValues(selectMaxRunnumber) // Map[String, List[String]] => Map[String, String]
.values // Map[String, String] => List[String]
def selectMaxRunnumber(fileNames: List[String]): String =
fileNames.map(f => f -> extractRunnumber(f))
.maxBy(p => p._2)
._1
我将 extractDate
和 extractRunnumber
实现留空。这些可以使用简单的正则表达式来完成 - 如果您遇到问题,请告诉我。