我使用Scala 2.9来处理一些Excel文件。它们都存储在目录中,文件名为Sales_yyyy_mm.xlsx
。
我编写了以下代码,以生成一个包含每个Excel的年,月和File
的数组:
val fileStruct = """Sales_(\d\d\d\d)_(\d\d).xlsx""".r
val excels = (new java.io.File(dirName)).listFiles
val files = for(file <- excels; fileStruct(year, month) <- file.getName)
yield(file, year, month)
文件数组正确计算到excels
。但files
为空。我检查了文件名,它们都匹配正则表达式(如果我使用match
/ case
重写我的代码,则没有问题。)
代码正确编译,类型按照我的预期推断,但它不起作用。我做错了什么?
答案 0 :(得分:4)
问题在于file.GetName
会返回String
- 或者从for-comprehension的角度来看,Seq[Char]
。现在,当您在for comprehension中使用模式匹配时,您将在映射或flatMapping之前应用过滤器。实际上,你这样做:
val files = excels.flatMap(
(file => file.getName().withFilter(
((x$0 => x$0 match {
case fileStruct((year @ _), (month @ _)) => true
case _ => false
})).map(
(x$1 => x$1 match {
case fileStruct((year @ _), (month @ _)) => (file, year, month)
}))))
问题是x$0
是Char
,因此它永远不会与正则表达式相匹配。
答案 1 :(得分:2)
我通过以下方式使其工作:
val fileStruct = """Sales_(\d\d\d\d)_(\d\d).xlsx""".r
val excels = (new java.io.File(dirName)).listFiles
val files = for{
file <- excels
year :: month :: _ <- fileStruct.unapplySeq(file.getName)
}
yield(file, year, month)
答案 2 :(得分:1)
如果您的目录中只有Sales_yyyy_mm_xlsx,请尝试以下操作:
scala> val files = for(file <- excels ; val fileStruct(year, month) = file.getName)
| yield(file, year, month);
如果没有:
excels.map(file => fileStruct.findFirstIn(file.getName) match {
| case Some(fileStruct(year, month)) => Some(file, year, month)
| case _ => None
| }).filterNot(_.isEmpty)
告诉我:
res3: Array[Option[(java.io.File, String, String)]] = Array(Some((./Sales_2012_03.xlsx,2012,03)), Some((./Sales_2012_04.xlsx,2012,04)))
我认为当正则表达式不匹配时会出现问题