2

I would like to know if there is a neat way of replacing all zeros in an array with the previous nonzero value in Scala. Similar to this question: pandas replace zeros with previous non zero value

I can achieve this for the case where there are no consecutive zeros with sliding:

scala> Array(1,2,3,0,5,6,7).sliding(2).map {case Array(v1, v2) => if (v2==0) v1 else v2}.toArray
res293: Array[Int] = Array(2, 3, 3, 5, 6, 7)

although I then have to append the first value (which I would do before converting to array).

The above code does not work if there are two consecutive zeros:

scala> Array(1,2,3,0,0,6,7).sliding(2).map {case Array(v1, v2) => if (v2==0) v1 else v2}.toArray
res294: Array[Int] = Array(2, 3, 3, 0, 6, 7)

The desired result is Array(2,3,3,3,6,7).

This would be easy to do with a for loop; is it possible with a functional approach?

3 Answers 3

4

Use scanLeft:

Array(1,2,3,0,5,6,7).scanLeft(0)({(left, right) => if (right == 0) then left else right}).tail
Sign up to request clarification or add additional context in comments.

2 Comments

Yes, this is "the right way" :) The only thing I'd change is { case(x, 0) => x; case (_, x) => x; } rather than the if/else
Yeah, this is what I learned in school, and I remember thinking it was pretty neat :) Personally I prefer the if/else when doing a simple numerical comparison, but it's a style preference.
3

There are probably lots of ways. You can do this with foldLeft for example:

Array(1,2,3,0,0,6,7)
    .foldLeft(List.empty[Int]){
        (acc, v) => if (v != 0) v :: acc else acc.head :: acc
    }.reverse.toArray

Comments

2

A recursive approach,

def f(xs: Array[Int], nonZ: Int): Array[Int] = {
  if (xs.isEmpty) xs
  else if (xs.head == 0) nonZ +: f(xs.tail, nonZ)
  else xs.head +: f(xs.tail, xs.head) 
}

which may be called for val xs = Array(1,2,3,0,0,6,7) like this

f(xs, xs.head)
Array(1, 2, 3, 3, 3, 6, 7)

To note the problem is not defined for a collection that starts with zeroes. Also to mention this recursive function makes repetitive calls to tail and head which may be reduced to one.

1 Comment

Thanks for your answer; Archeg's was more what I was looking for and I will add some logic to handle cases for collections starting with zeros. I learned from both answers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.