scala必知必会之列表的map,flatMap,zip和reduce

来源:互联网 发布:淘宝僵尸店宝贝上万个 编辑:程序博客网 时间:2024/05/21 09:12

作为一个scala从业人员,如果你不了解Map.flatMap.zip,reduce函数,那就别BB 了大笑(勿喷,仅代表原作者观点,与本人无关)

原文地址

---------------------------------------------------------------------------------------

通过这些函数,我们可以非常容易的处理列表的内容并结合Option对象工作。


Map: 通过Map我们可以将一个函数应用于列表的每一个元素并且将其作为一个新的列表返回。

scala> list1res3: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)scala> list1.map(x=>x*x)res4: List[Int] = List(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100)

一些函数可能返回Option元素。例如:

scala> val evenify = (x:Int) => if (x % 2 == 0) Some(x) else Noneevenify: Int => Option[Int] = <function1>scala> list1.map(evenify)res6: List[Option[Int]] = List(Some(0), None, Some(2), None, Some(4), None, Some(6), None, Some(8), None, Some(10))

这个栗子的问题是我们不想吃坏的,奥是不想管None.勿喷,我们可以是使用flatMap.

flatMap:

通过flatMap我们可以处理元素是序列的列表,将提供的函数应用于每个序列元素,并返回原始列表中,所有序列的所有元素,组成一个列表

scala> val list3 = 10 to 20 toListlist3: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)scala> val list2 = 1 to 10 toListlist2: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)scala> val list4 = List(list2, list3)list4: List[List[Int]] = List(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))scala> list4.flatMap(x=>x.map(y=>y*2))res2: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40) 

我们可以看到list4的元素是两个列表。我们调用flatmap分别处理这两个列表,并用map将这两个列表的元素平方,最后的结果是一个包含所有元素的平坦列表。

译者注:flatMap并不一定用于元素是序列的列表,他只需要应用的函数返回结果是GenTraversableOnce即可,例如:

scala> List(1,2,3,4,5)res0: List[Int] = List(1, 2, 3, 4, 5)scala> res0.flatMap(x => 1 to x )res1: List[Int] = List(1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5)
让我们回过头看一下之前看到过的evenify函数和之前返回的Option列表

scala> val list1 = 1 to 10 toListlist1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)scala> list1.map(evenify)res3: List[Option[Int]] = List(None, Some(2), None, Some(4), None, Some(6), None, Some(8), None, Some(10))scala> val list2 = list1.map(evenify)list2: List[Option[Int]] = List(None, Some(2), None, Some(4), None, Some(6), None, Some(8), None, Some(10))scala> list2.flatMap(x => x)res6: List[Int] = List(2, 4, 6, 8, 10) 


亦可以写成

scala> list1.flatMap(x=>evenify(x))res14: List[Int] = List(2, 4, 6, 8, 10)

另外两个可以用于列表的函数

Zip:

scala> val list = "Hello.World".toCharArraylist: Array[Char] = Array(H, e, l, l, o, ., W, o, r, l, d)scala> val list1 = 1 to 20 toListlist1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)scala> list.zip(list1)res30: Array[(Char, Int)] = Array((H,1), (e,2), (l,3), (l,4), (o,5), (.,6), (W,7), (o,8), (r,9), (l,10), (d,11))scala> list1.zip(list)res31: List[(Int, Char)] = List((1,H), (2,e), (3,l), (4,l), (5,o), (6,.), (7,W), (8,o), (9,r), (10,l), (11,d))
返回的列表长度取决于较短的列表,只要有一个列表到达了末尾zip函数就停止了。我们可以使用zipAll
函数来对较长列表的剩余元素进行处理:
scala> list.zipAll(list1,'a','1')res33: Array[(Char, AnyVal)] = Array((H,1), (e,2), (l,3), (l,4), (o,5), (.,6), (W,7), (o,8), (r,9), (l,10), (d,11), (a,12), (a,13), (a,14), (a,15), (a,16), (a,17), (a,18), (a,19), (a,20))

最后一个函数:reduce.使用reduce我们可以处理列表的每个元素并返回一个值。通过使用reduceLeft和reduceRight我们可以强制处理元素的方向(使用reduce方向是不被保证的)

scala> list1res51: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)scala> val sum = (x:Int, y:Int) => {println(x,y) ; x + y}sum: (Int, Int) => Int = <function2>scala> list1.reduce(sum)(1,2)(3,3)(6,4)(10,5)(15,6)(21,7)(28,8)(36,9)(45,10)(55,11)(66,12)(78,13)(91,14)(105,15)(120,16)(136,17)(153,18)(171,19)(190,20)res52: Int = 210scala> list1.reduceLeft(sum)(1,2)(3,3)(6,4)(10,5)(15,6)(21,7)(28,8)(36,9)(45,10)(55,11)(66,12)(78,13)(91,14)(105,15)(120,16)(136,17)(153,18)(171,19)(190,20)res53: Int = 210scala> list1.reduceRight(sum)(19,20)(18,39)(17,57)(16,74)(15,90)(14,105)(13,119)(12,132)(11,144)(10,155)(9,165)(8,174)(7,182)(6,189)(5,195)(4,200)(3,204)(2,207)(1,209)res54: Int = 210


0 0
原创粉丝点击