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:
According definition, foldLeft can do everything which required iteration of all elements of list. Really ?
Yes. Let’s understand by examples.
- Reverse the list:
def reverse(list: List[Int]): List[Int] = list.foldLeft[List[Int]](Nil)((acc, element) => element :: acc)
- 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)
- 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) }
- 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 ) }
- Combine two list:
def combine(list1: List[Int], list2: List[Int]) = list2.foldLeft[List[Int]](list1)((acc, element) => acc :+ element)
- 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 }
- 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) }
- 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 }
- Sum the List:
def sum(list: List[Int]): Int = list.foldLeft(0)(_ + _)
- 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))
- 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!!! 🙂
Reblogged this on knoldermanish.
LikeLike
Reblogged this on Anurag Srivastava.
LikeLike