Why I love foldLeft :)

FoldLeft is the one of the my favourite function in Scala. In this blog,  I will explain capabilities of foldLeft. After reading this blog foldLeft will be your favourite function if you like Scala. In this blog I am taking example of List’s foldLeft. Of course, It’s also available on many Scala collection like Vector, Set, Map,Option.

Let’s see foldLeft definition from Scala doc:
foldLeft
According definition, foldLeft can do everything which required iteration of all elements of list. Really ?

Yes. Let’s understand by examples.

  1. Reverse the list:
    def reverse(list: List[Int]): List[Int] =
     list.foldLeft[List[Int]](Nil)((acc, element) => element :: acc)
    
  2. Remove duplicate element from list:
     def dedupe(list: List[Int]): List[Int] =
    list.foldLeft[List[Int]](Nil)((acc, element) => if (acc.contains(element)) acc else acc :+ element)
    
  3. Split into two list. first list contains all element which satisfies the predicate  and remaining into second list.
     def span(list: List[Int], p: Int => Boolean): (List[Int], List[Int]) =
     list.foldLeft[(List[Int], List[Int])]((Nil, Nil)) { case ((posList, negList), element) =>
     if (p(element)) (posList :+ element, negList) else (posList, negList :+ element)
     }
    
  4. Splitting into two list not big deal 🙂 My use case is different. I have 4 predicate. That means split input list into four list according predicates. First list satisfy first predicate and second list   satisfy second predicate ..so on. discard otherwise.
     def span(list: List[Int], p1: Int => Boolean, p2: Int => Boolean, p3: Int => Boolean, p4: Int => Boolean): (List[Int], List[Int], List[Int], List[Int]) =
     list.foldLeft[(List[Int], List[Int], List[Int], List[Int])]((Nil, Nil, Nil, Nil)) { case ((p1List, p2List, p3List, p4List), element) =>
     (
     if (p1(element)) p1List :+ element else p1List,
     if (p2(element)) p2List :+ element else p2List,
     if (p3(element)) p3List :+ element else p3List,
     if (p4(element)) p4List :+ element else p4List
     )
     }
    
  5. Combine two list:
     def combine(list1: List[Int], list2: List[Int]) =
     list2.foldLeft[List[Int]](list1)((acc, element) => acc :+ element)
    
  6. Zip two list:
      def zip(list1: List[Int], list2: List[String]): List[(Int, String)] =
        if (list1.length > list2.length) {
          list2.foldLeft[(List[Int], List[(Int, String)])]((list1, Nil)) {
            case ((list, zip), element) => (list.tail, zip :+ (list.head, element))
          }._2
        } else {
          list1.foldLeft[(List[String], List[(Int, String)])]((list2, Nil)) {
            case ((list, zip), element) => (list.tail, zip :+ (element, list.head))
          }._2
        }
    
  7. Unzip the List :
      def unzip(list: List[(Int, String)]): (List[Int], List[String]) =
        list.foldLeft[(List[Int], List[String])]((Nil, Nil)) {
          case ((list1, list2), (number, str)) => (list1 :+ number, list2 :+ str)
        }
    
  8. Sort the list:
      def sort(list: List[Int]): List[Int] =
        list.foldLeft[List[Int]](Nil) { (acc, element) => insert(element, acc) }
    
      def insert(elem: Int, list: List[Int]): List[Int] =
        list match {
          case head :: tail => if (head <= elem) head :: insert(elem, tail) else elem :: list
          case Nil => elem :: Nil
        }
    
  9. Sum the List:
    def sum(list: List[Int]): Int = list.foldLeft(0)(_ + _)
    
  10. Implement own map using foldLeft:
        def map(list: List[Int], f: Int => Int): List[Int] =
        list.foldLeft[List[Int]](Nil)((acc, element) => acc :+ f(element))
    
  11. Of course you can implement flatMap using foldLeft 🙂
    def flatMap(list: List[Int], f: Int => List[Int]): List[Int] =
    list.foldLeft[List[Int]](Nil)((acc, element) => acc ++ f(element))
    

May be these examples make you happy and give the understanding of foldLeft.

All example are available here.
Happy Hacking!!! 🙂