匹配元素序列中的多个元素

时间:2015-03-14 13:59:41

标签: scala pattern-matching

我有一系列元素,特别是字节,我希望将它们匹配到更高级别的内容,例如: 16位整数。天真的方法看起来像这样:

val stream: Seq[Byte] = ???
def short(b1: Byte, b0: Byte): Short = ???

stream match {
    case Seq(a1, a0, b1, b0, _*) => (short(a1, a0), short(b1, b0))
    // ...
}

我设法做的是这样,使用object short_:: unapply方法:

stream match {
    case a short_:: b short_:: _ => (a, b)
    // ...
}

但是,我真的不能说我喜欢这里的语法,因为它看起来不像常规模式匹配。我写这样的东西会更高兴:

stream match {
    case Short(a) :: Short(b) :: _ => (a, b)
    // ...
}

当然,使用标识符Short::可能很难/一个坏主意,但我认为这是为了解决这个问题的重点。

是否可以编写自定义模式匹配代码,产生与此类似的语法?我在这里限制自己到流的固定宽度内容(虽然不是一个宽度:例如Short和Int都应该是可能的),但我需要能够匹配流的其余部分,如{{ 1}}或:: tail

1 个答案:

答案 0 :(得分:2)

试试这个

object ::: {
  def unapply(seq: Seq[Byte]): Option[(Int, Seq[Byte])] = {
    if(seq.size > 1) Some(seq(0) * 256 + seq(1), seq.drop(2))
    else None
  }
}


val list = List[Byte](1,2,3,4,5,6,7,8)
list match {
  case a ::: b ::: rest => println(a + ", " + b + ", " + rest)
}

你也可以混合使用字节,短路和整数。

object +: {
  def unapply(seq: Seq[Byte]): Option[(Byte, Seq[Byte])] = {
    if(seq.size > 0) Some(seq.head, seq.tail)
    else None
  }
}

object ++: {
  def unapply(seq: Seq[Byte]): Option[(Short, Seq[Byte])] = seq match {
    case a +: b +: rest => Some(((a&0xFF) << 8 | (b&0xFF)).toShort, rest)
    case _ => None
  }
}

object +++: {
  def unapply(seq: Seq[Byte]): Option[(Int, Seq[Byte])] = seq match {
    case a ++: b ++: rest => Some((a&0xFFFF) << 16 | (b&0xFFFF), rest)
    case _ => None
  }
}

val list = List[Byte](1,2,3,4,5,6,7,8,9,10,11,12)
list match {
  case a +: b ++: c +++: rest => println(a + ", " + b + ", " + c + ", " + rest)
}

+:表示左边的变量是一个字节,++:表示左边的变量是short,+++表示int。顺便说一句。出于某种原因,只有当对象的名称以&#34;:&#34;。

结尾时,这才有效