St.Antario
St.Antario

Reputation: 27385

How to split list in pattern matching?

I have the following list:

val lst: List[Char] = //...

I would like to use it in pattern matching as follows:

lst match {
    case firstPart :: '|' :: theRestOfTheList =>
        //do something with them
}

The problem is firstPart is treated as a single character. But I want it to be the part of the list before the first '|'.

Is it possible to do so in a concise way in Scala?

Upvotes: 2

Views: 887

Answers (3)

Andrei T.
Andrei T.

Reputation: 2480

There's yet another way to do this if you're ok with turning the list of chars in a string and then matching it with a regex - I assumed you had the original list of chars from a string. Anyway here's the solution:

val pattern = """(.*)\|(.*)""".r
lst.mkString match {
  case pattern(left, right) => // do something with left & right strings
  case _                    => // do something else
}

Hope that helps!

Upvotes: 2

hoyland
hoyland

Reputation: 1824

It sounds like span almost is what you want, which splits the list into the longest prefix satisfying some predicate and the rest of the list :

val (firstPart, secondPart) = lst.span(_ != '|')

The caveat is that secondPart will have | as the first element, so your "real" second part would be secondPart.tail.

Upvotes: 1

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

Yes, using custom extractor.

Scala REPL

scala> val str: List[Char] = "foo|bar".toList
str: List[Char] = List(f, o, o, |, b, a, r)

scala> :paste
// Entering paste mode (ctrl-D to finish)

 object SuperSplit {
    def unapply(list: List[Char]): Option[(List[Char], List[Char])] = {
      val (a, b) = list.splitAt(list.indexOf('|'))
      Some((a, b.tail))
    }
  }

// Exiting paste mode, now interpreting.

defined object SuperSplit

scala> str match { case SuperSplit(a, b) => println(s"$a  $b")}
List(f, o, o)  List(b, a, r)

Warning: Take care of corner cases where list is empty and others

Special syntax

scala> :paste
// Entering paste mode (ctrl-D to finish)

object `|` {
    def unapply(list: List[Char]): Option[(List[Char], List[Char])] = {
      val (a, b) = list.splitAt(list.indexOf('|'))
      Some((a, b.tail))
    }
  }

// Exiting paste mode, now interpreting.

defined object $bar

scala> str match { case `|`(a, b) => println(s"$a  $b")}
List(f, o, o)  List(b, a, r)

Upvotes: 4

Related Questions