Eduardo
Eduardo

Reputation: 8392

Matching Regex in For Comprehensions

I am using Scala 2.9 to process some Excel files. They are all stored in a directory and have the filename Sales_yyyy_mm.xlsx.

I wrote the following code, to produce an array with the year, month and File of each Excel:

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)

The array of files is computed correctly into excels. However files is empty. I have checked the file names and they all match the regex (if I rewrite my code using match/case there is no problem).

The code compiles correctly and the types are inferred as I expect them, but it doesn't work. What am I doing wrong?

Upvotes: 0

Views: 477

Answers (3)

Eduardo
Eduardo

Reputation: 8392

I made it work in the following way:

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)

Upvotes: 2

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297205

The problem is that file.GetName returns a String -- or, from the for-comprehension's point of view, a Seq[Char]. Now, when you use a pattern matching in a for comprehension, you are applying a filter before mapping or flatMapping. In effect, you are doing this:

  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)
      }))))

The problem is that x$0 is a Char, so it will never match the regex pattern.

Upvotes: 4

twillouer
twillouer

Reputation: 1178

If you only have Sales_yyyy_mm_xlsx on your directory, try this :

scala> val files = for(file <- excels ; val fileStruct(year, month) = file.getName)
     | yield(file, year, month);

and if not :

excels.map(file => fileStruct.findFirstIn(file.getName) match {
     |  case Some(fileStruct(year, month)) => Some(file, year, month)
     |  case _ => None
     | }).filterNot(_.isEmpty)

give me :

res3: Array[Option[(java.io.File, String, String)]] = Array(Some((./Sales_2012_03.xlsx,2012,03)), Some((./Sales_2012_04.xlsx,2012,04)))

I think the problem appear when the regexp doesn't match

Upvotes: 1

Related Questions