【问题标题】:how to do scala pattern matching on array?如何在数组上进行scala模式匹配?
【发布时间】:2021-04-08 22:34:49
【问题描述】:

我是一个新的 Scala 程序员,我有一个关于 Scala 数组模式匹配的问题:

def countErased(sorted: Array[Array[Int]], acc: Int): Int = {
    sorted match{
        case Array() | Array(_) => acc
        case Array(h,n,_*) =>
            if(n(0) < h(1)){
                countErased(Array(h,_*), acc+1)
            }else{
                countErased(Array(n,_*), acc)
            }
    }
}

基本上我想要做的是:当我们有一个长度大于 2 的数组时,如果 n(0)

"error: missing parameter type for expanded function ((<x$1: error>) => x$1.$times) (in solution.scala)
                countErased(Array(h,_*), acc+1)" 

怎么了?

【问题讨论】:

  • 这是一个完美的例子,你应该使用列表而不是数组,模式匹配有一些限制,由某些实现细节和类型层次结构的设置方式(以及当然也擦除)。可以使用别名和类型转换来完成这项工作,但它会非常难看。
  • 补充@sinanspd 这段代码也非常高效,因为 Arrays 在所有这些操作上都很慢,请改用 List。会更简单、更美观、更高效、更安全。

标签: arrays scala functional-programming pattern-matching


【解决方案1】:

您的直接问题已在另一个答案中得到解决:您只需为 splat 命名,例如 rest@_*,并使用它来引用它。

我只是想支持 cmets 的建议,并提到您应该使用 List 而不是数组(如果方便的话,您可以使用调用 countErased(array.toList, 0) 的包装函数)。

scala 中的match 使用列表看起来也更漂亮和惯用:

def countErased(sorted: List[Array[Int]], acc: Int) = sorted match {
  case h@Array(_, x, _*) :: Array(y, _*) :: tail if y < x => countErased(h :: tail, acc+1) 
  case _ :: n :: tail => countErased(n :: tail, acc)
  case _ => acc
}

附带说明,与原始实现的一个区别是,如果其中一个数组恰好包含少于两个元素,则此实现不会抛出。

【讨论】:

    【解决方案2】:

    欢迎来到 Scala 社区 :)

    我同意其他 cmets,倾向于推荐 SeqList,因为它们是不可变的(尤其是在递归设置中更可取)且高效。

    虽然Array 是可行的,但您的代码几乎可以工作,我只需要添加一个名称给_* 捕获(这就是rest@ 正在做的事情),然后是@ 的一个实例987654326@,圣我可以在递归调用中重复使用它:

      def countErased(sorted: Array[Array[Int]], acc: Int): Int = {
        sorted match {
          case Array() | Array(_) => acc
          case Array(h, n, rest@_*) =>
            if (n(0) < h(1)) {
              countErased(h +: rest.toArray, acc + 1)
            } else {
              countErased(n +: rest.toArray, acc)
            }
        }
      }
    
    

    【讨论】:

      【解决方案3】:

      其实你已经很接近了。您只需要记住 sorted 变量仍然可供您使用,并且它包含构建下一个 Array 所需的内容。

      def countErased(sorted: Array[Array[Int]], acc: Int): Int =
        sorted match { 
          case Array() | Array(_) => acc
          case Array(h, n, _*) =>
            if (n(0) < h(1))  countErased(h +: sorted.drop(2), acc+1)
            else              countErased(     sorted.tail,    acc)
        }
      

      如前所述,以这种方式操作数组效率非常低,但如果您坚持使用Array[Array[Int]],这将起作用。

      【讨论】:

        猜你喜欢
        • 2011-10-02
        • 2013-12-15
        • 2015-04-02
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多