【问题标题】:Why zip does not work with match case in Scala?为什么 zip 不适用于 Scala 中的匹配大小写?
【发布时间】:2018-02-28 01:22:42
【问题描述】:

我想压缩两个列表并进行模式匹配,但似乎 zip 和 match 产生错误。我不明白为什么会出现这样的错误。

以下示例是简化版本。

这行得通

val l = List((1, 2), (3, 4), (5, 6))
l.map { case(a, b) => println(s"First is $a, second is $b") }

这不起作用

val l1 = List(1,2,3)
val l2 = List(4,5,6)
l1.zip(l2)
l1.zip(l2).map { case(a, b) => a match {case 1 => println(s"First is $a, second is $b") }}

错误信息

scala.MatchError: 2 (of class java.lang.Integer)
  at .$anonfun$res15$1(<console>:14)
  at .$anonfun$res15$1$adapted(<console>:14)
  at scala.collection.immutable.List.map(List.scala:287)
  ... 28 elided

【问题讨论】:

    标签: scala


    【解决方案1】:

    zip 可以与match 一起使用,但如果您使用map(),则必须为您将遇到的所有条件提供匹配项。这就是默认case 派上用场的地方。

    如果您真的只对a == 1 所在的case 感兴趣,并且只想忽略所有其他条件,请使用collect() 而不是map()

    l1.zip(l2).collect{case (1, b) => println(s"First is 1, second is $b")}
    

    这是可行的,因为collect() 将部分函数作为其参数,因此与其case 匹配的输入是好的,其他所有内容都将被忽略。另一方面,map() 将函数(不是部分函数)作为其参数,这意味着它必须接受并处理所有输入,因此如果您使用模式匹配,那么每种情况都必须匹配。

    【讨论】:

      【解决方案2】:

      您的编译器应该很好地警告“您缺少默认模式匹配 case _ =&gt;”。

      它与zip 无关,而是与“模式匹配”有关。

      工作示例;

      scala> List(1,2,3).zip(List(4,5,6)).map { case(a, b) => 
              a match {case 1 => println(s"First is $a, second is $b") 
                       case _ => println("Oops I missed it")}}
      
      First is 1, second is 4
      Oops I missed it
      Oops I missed it
      res5: List[Unit] = List((), (), ())
      

      另外,如果您只是打印,请使用 foreach 函数而不是 map,因为数学上的 map 应该会返回一些数据。 foreach 是一劳永逸。

      scala> List(1,2,3).zip(List(4,5,6)).foreach { case(a, b) => 
                a match { 
                   case 1 => println(s"First is $a, second is $b") 
                   case _ => println("Oops I missed it")}}
      
      First is 1, second is 4
      Oops I missed it
      Oops I missed it
      

      另请阅读 - Scala case match default value

      还有Chapter - 9, Pattern matching/ stackoverflow doc

      【讨论】:

        【解决方案3】:

        你少了一对括号

        @ val list1 = List(1, 2, 3)
        val llist1: List[Int] = List(1, 2, 3)
        @ val list2 = List(5, 6, 7)
        lislist2: List[Int] = List(5, 6, 7)
        @ list1.zip(list2)
        res2: List[(Int, Int)] = List((1, 5), (2, 6), (3, 7))
        
        @ list1.zip(list2) foreach { case ((a, b)) => println(s"first is $a and then is $b") }
        

        这个输出

        first is 1 and then is 5
        first is 2 and then is 6
        first is 3 and then is 7
        

        代码和你写的一样,只是我用了一个额外的( 和这个) 来修补元组。

        【讨论】:

          猜你喜欢
          • 2016-07-03
          • 2021-12-28
          • 1970-01-01
          • 2013-12-07
          • 1970-01-01
          • 1970-01-01
          • 2019-10-02
          • 2017-07-02
          相关资源
          最近更新 更多