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?

Community
  • 1
  • 1

3 Answers3

4

Use scanLeft:

Array(1,2,3,0,5,6,7).scanLeft(0)({(left, right) => if (right == 0) then left else right}).tail
gardenhead
  • 2,299
  • 2
  • 19
  • 17
  • 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` – Dima Jan 06 '16 at 21:05
  • 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. – gardenhead Jan 06 '16 at 21:16
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
Archeg
  • 8,364
  • 7
  • 43
  • 90
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.

elm
  • 20,117
  • 14
  • 67
  • 113
  • 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. – IdRatherBeCoding Jan 06 '16 at 20:21