简体   繁体   中英

how to do scala pattern matching on array?

i am a new Scala programmer and I have a question on Scala Array pattern matching:

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)
            }
    }
}

Basically what i want to do is: when we have an Array of length longer than 2, if n(0)< h(1), call function recursively with a new Array of the head and whatever as the tail. otherwise call function with a new Array of the next and whatever as the tail. But this code gets me an error:

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

What is wrong?

Welcome to the Scala community:)

I concur with other comments, Seq and List tend to be recommended since they're immutable (much preferable especially in a recursive setting) and efficient.

It's doable with Array though, your code is almost working, all I had to add was giving a name to the _* capture (that's what the rest@ is doing), which is then an instance of Seq[Array] , st I could re-use it in the recursive call:

  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)
        }
    }
  }

Your immediate problem is addressed in the other answer: you just need to give a name to the splat, like rest@_* , and use that to refer to it.

I just want to second the advice from the comments, and mention that you should be using a List rather that an array (you can have a wrapper function that calls countErased(array.toList, 0) if that's convenient).

The match in scala also looks much nicer and idiomatic with lists:

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
}

As a side note, one difference from your original implementation is that this one does not throw if one of the arrays happens to have fewer than two elements.

You're actually pretty close. You just need to remember that the sorted variable is still available to you and it contains what you need to construct the next 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)
  }

As mentioned, it's pretty inefficient to manipulate arrays in this manner but if you're stuck with Array[Array[Int]] this will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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