我有以下清单:

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


我想在模式匹配中使用它,如下所示:

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


问题是firstPart被视为单个字符。但我希望它成为第一个'|'之前列表的一部分。

是否可以在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)



警告:请注意列表为空且其他情况很少的情况


特殊语法

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)

09-30 15:33
查看更多