1

Does anybody know if there is a short way of doing this without passing each value:

case class Person(title: String, first: String, last: String)

val name = """(Mr|Mrs|Ms)\. ([A-Z][a-z]+) ([A-Z][a-z]+)""".r
val name(title, first, last) = "Mr. James Stevens"

Person.tupled((title, first, last))

I'm looking for a way to get the result of the regex as a tuple to pass it directly to Person.tupled().

Thanks, Torben

Torben
  • 1,290
  • 5
  • 22
  • 41

2 Answers2

0

This is not entirely possible as unapplySeq returns a List. For the reasoning and some possibilities, see this SO question on list to tuple.

The best solution would probably be pattern matching

Person.tupled(nameString match {
  case name(first, middle, last) => (first, middle, last)
})
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
0

You could write your own extractor for this:

object NameRegex {
    private val name = """(Mr|Mrs|Ms)\. ([A-Z][a-z]+) ([A-Z][a-z]+)""".r
    def unapply(x: String) = name.unapplySeq(x).collect {
        case(List(title, first, last)) => (title, first, last)
    }
}

And then you could do

val NameRegex(tuple) = "Mr. Charles Darwin"
Person.tupled(tuple)

Or:

"Mr. Ben Reich" match {
    case NameRegex(tuple) => Person.tupled(tuple)
}

Or you could make the NameRegex object match to the Person object:

object NameRegex {
    private val name = """(Mr|Mrs|Ms)\. ([A-Z][a-z]+) ([A-Z][a-z]+)""".r
    def unapply(x: String) = name.unapplySeq(x).collect {
        case(List(title, first, last)) => Person(title, first, last)
    }
}

So then you can extract the person case class in one step:

val NameRegex(p) = "Mr. Barack Obama" //p is Person("Mr", "Barack", "Obama")
val NameRegex(p@Person(title, first, last)) = "Mr. Barack Obama"
Ben Reich
  • 16,222
  • 2
  • 38
  • 59