Scala技术问询:为何flatMap返回IndexedSeq[List[(Char,Int)]]而map返回另一种类型
为什么flatMap和map返回的类型不一样?
别着急,这完全是因为map和flatMap这两个方法的设计目标和行为逻辑根本不同,我结合你的代码一步步给你拆解:
先搞清楚你的ind变量是什么
先看你combinations函数里的这段代码:
val ind = for { occ <- occurrencesV x <- (occ._2 to 1 by -1) } yield (occ._1, x)
当你传入List(('a', 2), ('e', 1), ('t', 2))时,ind会生成一个IndexedSeq[(Char, Int)],具体内容是:
IndexedSeq(('a',2), ('a',1), ('e',1), ('t',2), ('t',1))
这个是后续操作的基础,先记下来。
分析flatMap的行为(你的combinations函数)
你这里调用的是:
(1 to 2).flatMap(ind.combinations)
我们拆分来看:
(1 to 2)是一个包含1和2的Range集合。- 对Range里的每个数字
n(先1,再2),调用ind.combinations(n)——这个方法的作用是生成原集合ind中所有长度为n的子序列,返回的是Iterator[List[(Char, Int)]]。比如:- 当
n=1时,返回的是包含5个单元素List的迭代器:List(('a',2)), List(('a',1)), List(('e',1)), List(('t',2)), List(('t',1)) - 当
n=2时,返回的是包含所有两两组合的List的迭代器,比如List(('a',2), ('a',1)), List(('a',2), ('e',1))等等
- 当
- 重点来了:
flatMap的作用是把每个函数返回的集合(这里是Iterator里的List)都“拆开来”,把里面的元素直接放到最终的集合里。也就是说,它会把两个Iterator里的所有List都取出来,合并成一个大的IndexedSeq,所以最终返回的是IndexedSeq[List[(Char, Int)]]——每个元素都是一个长度为1或2的List。
分析map的行为(结合你的描述)
你说map返回的是IndexedSeq[(Char, Int)],这说明你的map操作是直接对单个元素进行转换,而不是处理返回集合的函数。
举个符合你返回类型的例子,如果你的comT函数是类似这样的:
def comT(occurrencesV: List[(Char, Int)]): IndexedSeq[(Char, Int)] = { val ind = for { occ <- occurrencesV x <- (occ._2 to 1 by -1) } yield (occ._1, x) // 这里用map直接处理ind里的每个元素,比如做一些简单转换 ind.map(item => (item._1, item._2 + 1)) }
那map的逻辑是:对ind里的每个(Char, Int)元素应用一个函数(比如把数字加1),然后把每个函数的结果直接组成新的集合。此时函数的输入是(Char, Int),输出也是(Char, Int),所以最终返回的是IndexedSeq[(Char, Int)]——和原集合的元素类型一致,只是每个元素被转换过。
如果你的comT是对(1 to 2)用map的话,返回的会是IndexedSeq[Iterator[List[(Char, Int)]]](因为map只是把每个n对应的Iterator直接放到集合里,不会扁平化),但你描述的返回类型说明你是直接操作了ind的单个元素。
核心总结
map:一对一转换,输入一个元素,输出一个元素,最终集合的元素类型是转换后的类型,集合的“层级”不变。flatMap:一对多转换后扁平化,输入一个元素,输出一个集合,然后把所有这些集合的元素合并成一个单层集合,最终集合的元素类型是输出集合里的元素类型。
内容的提问来源于stack exchange,提问作者Aavik
相关产品推荐
相关产品推荐

