I have a list like:
val arr = Array(\"a\", \"\", \"\", \"b\", \"c\", \"\")
I am looking for a way to create:
Array(\"a\", \"a\"
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.