Map, Scan, Fold and Reduce
Assume we have items varitems //List(1, 2, 6, 4, 2, 1) (result)
Map function
We can map each item to another value, but we need to define how to do it. We need unary operator or single argument functiondef how1(currentItem : Int) = currentItem * 2and then apply it to each item
items.map(how1) //List(2, 4, 12, 8, 4, 2) (result)or
items.map(how1(_)) //List(2, 4, 12, 8, 4, 2) (result)We can replace
items.map(how1) //List(2, 4, 12, 8, 4, 2) (result)with
val result0 = how1(items(0)) // 2 val result1 = how1(items(1)) // 4 val result2 = how1(items(2)) // 12 // ... val resultn = how1(items(n)) // 2 val result = List(result0, ..., resultn) // List(2, 4, 12, 8, 4, 2)Since vars result0, result1, ... resultn are independent we can evaluate them in any order.
Scan function
If we assume some processing order of items (e.g. from left (first to last) or from right (last to first)), then we can make use of previous result in subsequent calculation. That means we can scan items.We must define how to do_something_with previous result and current item. We need binary operator or two argument function
val result0 = do_something_with(???, items(1)) val result1 = do_something_with(result0, items(1)) val result2 = do_something_with(result1, items(2)) // ... val resultn = do_something_with(resultn-1, items(n)) val result = List(result0, ..., resultn)
def how2(prevResult : Int, currentItem : Int)But for result0 there's no previous result, instead we provide some_input
= prevResult * currentItem + 1
val result0 = do_something_with(some_input, items(1))Replace do_something_with with how2.
val input = ??? val result0 = how2(input, items(1)) val result1 = how2(result0, items(1)) val result2 = how2(result1, items(2)) // ... val resultn = how2(resultn-1, items(n)) val result = List(input, result0, ..., resultn)Then we can shorten to form
items.scan(input)(how2)Time to provide input value
items.scan(0)(how2v)Code result
List(0, 1, 3, 19, 77, 155, 156)
how2(0, 1)=1 how2(1, 2)=3 how2(3, 6)=19 how2(19, 4)=77 how2(77, 2)=155 how2(155, 1)=156
Execution time: 1 Result scan returns input followed by calculated results
input :: results
Scan function examples
Examples List itemsitems //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.scan(0)(_+_)
0 1 3 9 13 15 16
Product of items
items.scan(1)(_*_)
1 1 2 12 48 96 96
As expression
items.scan("input")("f(" + _ + ", " + _ + ")")
input f(input, 1) f(f(input, 1), 2) f(f(f(input, 1), 2), 6) f(f(f(f(input, 1), 2), 6), 4) f(f(f(f(f(input, 1), 2), 6), 4), 2) f(f(f(f(f(f(input, 1), 2), 6), 4), 2), 1)
empty list
List().scan(0)(_+_) //List(0) (result)single element list
List(0).scan(0)(_+_) //List(0, 0) (result)
Fold function
Scan function returns input and all intermediate results. If we need only last of them then we can fold items.items.scan(0)(how2)
0 1 3 19 77 155 156
If we need only last result, we can use
items.scan(0)(how2).last //156 (result)or shorter form fold instead of scan
items.fold(0)(how2) //156 (result)
Fold function examples
Examples List itemsitems //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.fold(0)(_+_) //16 (result)Product of items
items.fold(1)(_*_) //96 (result)As expression
items.fold("input")("f(" + _ + ", " + _ + ")")f(f(f(f(f(f(input, 1), 2), 6), 4), 2), 1)
empty list
List().fold(0)(_+_) //0 (result)single element list
List(0).fold(0)(_+_) //0 (result)
Reduce function
We can split itemsitems //List(1, 2, 6, 4, 2, 1) (result)into head
items.head //1 (result)and tail
items.tail //List(2, 6, 4, 2, 1) (result)then use scan function
items.tail.scan(items.head)(how2) //List(1, 3, 19, 77, 155, 156) (result)if we need just last element...
items.tail.fold(items.head)(how2) //156 (result)Or use shorter form
items.reduce(how2) //156 (result)Examples List items
items //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.reduce(_+_) //16 (result)Product of items
items.reduce(_*_) //96 (result)As expression
items.map(_.toString).reduce("f(" + _ + ", " + _ + ")")f(f(f(f(f(1, 2), 6), 4), 2), 1)
empty list
List[Int]().reduce(_+_)
Exception:empty.reduceLeft
single element list
List[Int](0).reduce(_+_) //0 (result)
Left and Right functions
items.map is not left nor right items.scan is eqivalent to items.scanLeftitems.scan(0)(_+_) //List(0, 1, 3, 9, 13, 15, 16) (result)
items.scanLeft(0)(_+_) //List(0, 1, 3, 9, 13, 15, 16) (result)items.fold is eqivalent to items.foldLeft
items.fold(0)(_+_) //16 (result)
items.foldLeft(0)(_+_) //16 (result)items.reduce is eqivalent to items.reduceLeft
items.reduce(_+_) //16 (result)
items.reduceLeft(_+_) //16 (result)
scanRight
items.scanRight(0)(_+_) //List(16, 15, 13, 7, 3, 1, 0) (result)Examples List items
items //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.scanRight(0)(_+_)
16 15 13 7 3 1 0
Product of items
items.scanRight(1)(_*_)
96 96 48 8 2 1 1
As expression
items.scanRight("input")("f(" + _ + ", " + _ + ")")
f(1, f(2, f(6, f(4, f(2, f(1, input)))))) f(2, f(6, f(4, f(2, f(1, input))))) f(6, f(4, f(2, f(1, input)))) f(4, f(2, f(1, input))) f(2, f(1, input)) f(1, input) input
empty list
List[Int]().scanRight(0)(_+_) //List(0) (result)single element list
List(0).scanRight(0)(_+_) //List(0, 0) (result)
foldRight
items.foldRight(0)(_+_) //16 (result)Examples List items
items //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.foldRight(0)(_+_) //16 (result)Product of items
items.foldRight(1)(_*_) //96 (result)As expression
items.foldRight("input")("f(" + _ + ", " + _ + ")")f(1, f(2, f(6, f(4, f(2, f(1, input))))))
empty list
List[Int]().foldRight(0)(_+_) //0 (result)single element list
List(0).foldRight(0)(_+_) //0 (result)
reduceRight
items.reduce(_+_) //16 (result)Examples List items
items //List(1, 2, 6, 4, 2, 1) (result)Sum of items
items.reduceRight(_+_) //16 (result)Product of items
items.reduceRight(_*_) //96 (result)As expression
items.map(_.toString).reduceRight("f(" + _ + ", " + _ + ")")f(1, f(2, f(6, f(4, f(2, 1)))))
empty list
List[Int]().reduceRight(_+_)
Exception:Nil.reduceRight
single element list
List[Int](0).reduceRight(_+_) //0 (result)
No comments:
Post a Comment