Scala: Fill the gaps in a List with last non-empty value

前端 未结 3 836
灰色年华
灰色年华 2021-01-24 18:37

I have a list like:

val arr = Array(\"a\", \"\", \"\", \"b\", \"c\", \"\")

I am looking for a way to create:

Array(\"a\", \"a\"         


        
相关标签:
3条回答
  • 2021-01-24 19:16

    Not sure if this is an elegant way, but figured out one solution:

    var temp = "" 
    arr.map{ case "" => { temp }; case v => {temp=v; v } }
    
    0 讨论(0)
  • 2021-01-24 19:27

    You can try with fold, the easy (to understand) approach is fold left:

    (Array.empty[String] /: arr) {
        case (prev, "") => prev :+ prev.lastOption.getOrElse("");
        case (prev, l) => prev :+ l
    }
    
    > res01: Array[String] = Array(a, a, a, b, c, c)
    

    This builds a new array from the previous by appending arr elements or the resulting list's last depending on whether the source element is the empty string or not.

    You can also write it as:

    (Array.empty[String] /: arr) {
        case (Array(), l) => Array(l)
        case (prev, "") => prev :+ prev.last;
        case (prev, l) => prev :+ l
    }
    

    It can be optimized by using lists and prepend:

    {(List.empty[String] /: arr) {
        case (Nil, l) => l::Nil
        case (h::tail, "") => h::h::tail;
        case (prev, l) => l::prev
    } reverse } toArray
    

    In case you don't like the symbolic version of the fold left and fold right methods. Here it comes with its textual identifier:

    arr.foldLeft(Array.empty[String]) {
        case (prev, "") => prev :+ prev.lastOption.getOrElse("");
        case (prev, l) => prev :+ l
    }
    
    arr.foldLeft(List.empty[String]) {
        case (Nil, l) => l::Nil
        case (h::tail, "") => h::h::tail;
        case (prev, l) => l::prev
    }.reverse toArray
    

    Its exactly the same approach and implementation but with a different name.

    0 讨论(0)
  • I think Mohitt's answer is a clear solution ... but Pablo Francisco Pérez Hidalgo is right that there are side effects

    Maybe we could include the variable inside of a function to avoid changing the temp variable by some other developers

    (x: Array[String]) => { var last = ""; x.map { v => if (v != "") last = v; last } }
    

    to be used like this:

    val fillEmpty = (x: Array[String]) => { var last = ""; x.map { v => if (v != "") last = v; last } }
    fillEmpty(arr)
    
    0 讨论(0)
提交回复
热议问题