coder25
coder25

Reputation: 2393

Fold left to create a immutable list

I am trying to create a list of string and then concatenate them using mkstring

List("a", "b1")
    .foldLeft(ListBuffer.empty[String]) { (a, l) =>
    {
      if (StringUtils.isNotBlank(l))
        a += "abc" +l
      else a
    }
    }
    .mkString(";")

Output

abca;abcb1

I want to used a mutable list . Solution tried

List("a", "b1").
foldLeft(List[String]())((b,a) => b:+"abc"+a).mkString(";")

I can perform the empty check.Can we refactor it to better to get rid of if and else

   List("a", "b1","","c2").
   foldLeft(List[String]())((b,a) =>
    if (StringUtils.isNotBlank(a))
     b:+"abc"+a
    else b
).mkString(";")

Can anyone help

Upvotes: 0

Views: 517

Answers (1)

flavian
flavian

Reputation: 28511

List("a", "b1").foldLeft("") { case (acc, el) => acc + el }

You're slightly misusing foldLeft. The key thing to remember is that you pass in a function that takes an accumulator and the "current element", as well as a seed value, and feeds in the result of the "current" step as the "seed" or accumulator for the next step.

Reading from the top:

  • Take my list of List("a", "b1")
  • Starting from the empty string "" as the accumulator
  • For every element in the list, call the function against the "current" value of the accumulator.
  • In the above case, concatenate the "current" element to the existing accumulator.
  • Pass the result to the next step as the seed value.

There's no += like in your example, as you're not mutating the value, instead the return of the "current step", will be the initial accumulator value for the next step, it's all immutable.

In effect: - Step 0: acc = "", el = "a", so you get "" + "a" = "a"(this is the value of acc at the next stage) - Step 1: acc = "a", el = "b1", so you get "a" + "b1" = "ab1"

It's also worth nothing that the empty string "" is a the zero element for string concatenation, so there's no value in checking for empty.

For your specific example:

List("a", "b1").foldLeft("") { case (acc, el) =>
  if (el.isEmpty) acc else acc + "abc" + el
}

In your case, collect is probably better

l.collect {
  case s if s.nonEmpty =>  "abc" + s
} mkString ";"

Upvotes: 2

Related Questions