简体   繁体   English

在scala中,如何使用模式匹配来匹配具有指定长度的列表?

[英]In scala, how can I use pattern match to match a list with specified length?

My codes looks like this: 我的代码如下所示:

1::2::Nil match {
  case 1::ts::Nil => "Starts with 1. More than one element"
  case 1::Nil => "Starts with 1. Only one element"
}

I tried to use 1::ts::Nil to match the List who starts with 1 and whose length is greater than 1. It workes well for 2-element list, however, this pattern doesn't work for 3-element list , for example: 我尝试使用1::ts::Nil来匹配以1开头且长度大于1的List。它适用于2元素列表,但是,这种模式不适用于3-element list ,例如:

1::2::3::Nil match {
  case 1::ts::Nil => "Starts with 1. More than one element"
  case 1::Nil => "Starts with 1. Only one element"
}

This won't work..Does anyone have ideas about this? 这不会有用。有人对此有想法吗?

You don't have to match on Nil. 你不必在Nil上匹配。 What you could do instead is match on the rest. 你可以做的是与其他人匹配。

1::Nil match {
   case 1::ts::rest => "Starts with 1. More than one element"
   case 1::Nil => "Starts with 1. Only one element"
}

With this code rest is than either a List or Nil and you make sure that the element has more than 1 element with the match on ts and then rest 使用此代码,其余部分不是List或Nil,并且您确保该元素具有多个元素,并且匹配ts然后休息

By rearranging the cases and adding a third case for completeness (exhaustive matching), this captures the intended semantics, 通过重新排列案例并添加第三个案例来完成(穷举匹配),这可以捕获预期的语义,

1 :: 2 :: 3 :: Nil match {
  case 1 :: Nil => "Just one"
  case 1 :: xs => "One and more"
  case _ => "Unknown"
}

Note the second case extracts the first element and the rest which cannot be an empty list ( Nil ) since this possibility did not match in the first case: here, xs includes at least one more non empty list; 注意第二种情况提取第一个元素,其余不能是空列表( Nil ),因为这种可能性在第一种情况下不匹配:这里, xs包括至少一个非空列表; the last case covers empty lists. 最后一个案例包括空列表。

In addition to the other answers, you can also use the apply method of the companion List object like so: 除了其他答案,您还可以使用伴随List对象的apply方法,如下所示:

1::2::3::Nil match {
  case List(1, _, _*) => "Starts with 1. More than one element"
  case List(1) => "Starts with 1. Only one element"
}

To generalize this problem, you might write your own extractor. 要概括这个问题,您可以编写自己的提取器。 To match on lists of an arbitrary length with a given first element, you could: 要匹配具有给定第一个元素的任意长度的列表,您可以:

object HeadWithLength {
    def unapply[A](list: Seq[A]): Option[(Option[A], Int)] = 
        Some(list.headOption -> list.length)
}

And then you can match: 然后你可以匹配:

List(1, 3, 4) match {
    case HeadWithLength(Some(head), length) => println(s"Head is $head and length is $length") 
}

ts is matching one element of the list. ts匹配列表中的一个元素。 In your first case, ts matches 2 ie 1 in the list matches with 1 in the pattern statement, ts matches with 2 in the list and Nil in the list matches with Nil in the pattern statement and you don't get any MatchError 在你第一种情况下, ts匹配2即1在列表中匹配1的模式声明, ts用火柴2在列表中, Nil在列表中匹配Nil的模式声明,你没有得到任何MatchError


1 :: 2 :: Nil match {
    case 1 :: ts :: Nil => println("ts is "+ts)
                         "Starts with 1. More than one element"
    case 1 :: Nil       => "Starts with 1. Only one element"
  } //> ts is 2
   //| res1: String = Starts with 1. More than one element

In your second case, you are trying to match ts with both 2 and 3 which is not possible and hence it throws a MatchError. 在第二种情况下,您试图将ts与2和3匹配,这是不可能的,因此它会抛出MatchError。

If you want to do a pattern match based on size, you can do 如果你想根据大小进行模式匹配,你可以这样做

 
 1 :: 2 :: 3 :: Nil match {
    case 1 :: tail if tail.size > 1 => "Starts with 1. More than one element"
    case 1 :: Nil                   => "Starts with 1. Only one element"
  }   //> res0: String = Starts with 1. More than one element

If case in the pattern match can be any condition for your real use case 如果模式匹配中的情况可以是您的实际用例的任何条件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM