【问题标题】:How to split list in pattern matching?如何在模式匹配中拆分列表?
【发布时间】:2018-08-10 15:17:17
【问题描述】:

我有以下清单:

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

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

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

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

是否可以在 Scala 中以简洁的方式做到这一点?

【问题讨论】:

  • 也许"hello|world".split("\\|", 2) match { case Array(start, tail) => start + tail } ?
  • @XavierGuihot 其实可以解决!这是最简洁的吗?我怀疑可能还有别的东西......

标签: scala list pattern-matching


【解决方案1】:

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

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)

【讨论】:

    【解决方案2】:

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

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

    希望有帮助!

    【讨论】:

      【解决方案3】:

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

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

      需要注意的是secondPart| 作为第一个元素,因此您的“真实”第二部分将是secondPart.tail

      【讨论】:

      • 还要注意,如果没有|secondPart 是空的,所以secondPart.tail 会失败。
      猜你喜欢
      • 2016-07-05
      • 1970-01-01
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 2016-02-08
      • 2017-06-15
      相关资源
      最近更新 更多