如何在模式匹配中拆分列表?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在模式匹配中拆分列表?相关的知识,希望对你有一定的参考价值。

我有以下列表:

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

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

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

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

是否可以在Scala中以简洁的方式这样做?

答案

是的,使用自定义提取器。

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

还有另一种方法可以做到这一点,如果你可以在字符串中转换字符列表然后将其与正则表达式匹配 - 我假设你有一个字符串的原始字符列表。无论如何,这是解决方案:

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

希望有所帮助!

另一答案

这听起来像span几乎是你想要的,它将列表分成满足一些谓词和列表其余部分的最长前缀:

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

需要注意的是,secondPart|作为第一个元素,所以你的“真正的”第二部分将是secondPart.tail

以上是关于如何在模式匹配中拆分列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用对象列表在片段中实现newinstace模式[重复]

Android 上的 Kotlin:如何在片段中使用数据库中的 LiveData?

如何使用模式匹配在scala中获取一个nonEmpty列表?

在python中,如何通过匹配原始列表中的字符串模式从字符串列表中提取子列表

数着没有。在给定拆分原始列表的条件下,来自两个列表的匹配项

如何改进 Python 中列表的模式匹配