在正确理解中匹配正则表达式

时间:2013-02-08 22:56:07

标签: scala

我使用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重写我的代码,则没有问题。)

代码正确编译,类型按照我的预期推断,但它不起作用。我做错了什么?

3 个答案:

答案 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$0Char,因此它永远不会与正则表达式相匹配。

答案 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)))

我认为当正则表达式不匹配时会出现问题