为什么这个 flatMap return 是一个 Map 而不是一个列表?
Why does this flatMap return a Map instead of a list?
我正在尝试使用 flatMap 和 map
的组合将下面的 Map[T,List[T]]
转换为 List[T]
val numMap = Map(1 -> List(2) , 3 -> List(2,4))
val numPairs = numMap.flatMap{ case (n, nlist) => nlist.map (x => (x,n) ) }
结果是Map
res12: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3, 4 -> 3)
而不是预期的 List
List((2,1), (2,3), (4,3))
尽管我可以通过一系列 map
操作得到预期的结果
scala> numMap.map{ case (n, nlist) => nlist.map (x => (x,n) ).toList }.flatten
res20: scala.collection.immutable.Iterable[(Int, Int)] = List((2,1), (2,3), (4,3))
想了解为什么flatMap使用失败
I could arrive at the intended result with a sequence of map operations
scala> numMap.map{ case (n, nlist) => nlist.map(x => (x,n)).toList }.flatten
res20: scala.collection.immutable.Iterable[(Int, Int)] = List((2,1), (2,3), (4,3))
与其对所需的结果类型执行额外的转换,不如考虑使用 breakOut
:
import scala.collection.breakOut
val numPairs: List[(Int, Int)] =
numMap.flatMap{ case (n, nlist) => nlist.map((_, n)) }(breakOut)
// numPairs: List[(Int, Int)] = List((2,1), (2,3), (4,3))
使用 numPairs: List[(Int, Int)]
类型注释,breakOut
将结果数据收集到 List[(Int, Int)]
中,同时绕过中间集合的生成。
根据 scala doc 有两个版本的 flatMap
函数:一个 return 是一个新的可迭代集合 而 另外 return 是一张新地图 。
结果集合的类型由可迭代集合的静态类型决定,这有时可能会导致意想不到的结果。
简单来说,如果我们在 flatMap
参数 return 中提供的函数是单个元素,我们将是 returned 可迭代集合。另一方面,如果 flatMap
参数 return 中的函数是一个集合,我们将 return 编辑一个新的 Map。
例如这是您的输入变量:
scala> val numMap = Map(1 -> List(2) , 3 -> List(2,4))
如果我们 return 只有来自 flatMap
函数参数的单个元素,我们会得到 List
scala> numMap.flatMap{case(k,v) => v}
res0: List(2, 2, 4)
或(return单个元素的另一种方式)
scala> numMap.flatMap{case(k,v) => v.map(e => e)}
res1: List(2, 2, 4)
但是,如果我们 return 从 flatMap
中的函数中收集一个集合,我们将得到 Map
。我们在这里 returning 元组 (<element of list>, <key>)
scala> numMap.flatMap{case(k,v) => v.map(e => (e,k))}
res2: Map(2 -> 3, 4 -> 3)
如果我们想要 return 来自 flatMap
函数参数的集合,我们可以使用 case class
并获得 List
:
scala> case class MyCollection(a: Int, b: Int)
scala> numMap.flatMap{case(k,v) => v.map(e => MyCollection(e,k))}
res4: List(MyCollection(2,1), MyCollection(2,3), MyCollection(4,3))
我正在尝试使用 flatMap 和 map
的组合将下面的Map[T,List[T]]
转换为 List[T]
val numMap = Map(1 -> List(2) , 3 -> List(2,4))
val numPairs = numMap.flatMap{ case (n, nlist) => nlist.map (x => (x,n) ) }
结果是Map
res12: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3, 4 -> 3)
而不是预期的 List
List((2,1), (2,3), (4,3))
尽管我可以通过一系列 map
操作得到预期的结果
scala> numMap.map{ case (n, nlist) => nlist.map (x => (x,n) ).toList }.flatten
res20: scala.collection.immutable.Iterable[(Int, Int)] = List((2,1), (2,3), (4,3))
想了解为什么flatMap使用失败
I could arrive at the intended result with a sequence of map operations
scala> numMap.map{ case (n, nlist) => nlist.map(x => (x,n)).toList }.flatten res20: scala.collection.immutable.Iterable[(Int, Int)] = List((2,1), (2,3), (4,3))
与其对所需的结果类型执行额外的转换,不如考虑使用 breakOut
:
import scala.collection.breakOut
val numPairs: List[(Int, Int)] =
numMap.flatMap{ case (n, nlist) => nlist.map((_, n)) }(breakOut)
// numPairs: List[(Int, Int)] = List((2,1), (2,3), (4,3))
使用 numPairs: List[(Int, Int)]
类型注释,breakOut
将结果数据收集到 List[(Int, Int)]
中,同时绕过中间集合的生成。
根据 scala doc 有两个版本的 flatMap
函数:一个 return 是一个新的可迭代集合 而 另外 return 是一张新地图 。
结果集合的类型由可迭代集合的静态类型决定,这有时可能会导致意想不到的结果。
简单来说,如果我们在 flatMap
参数 return 中提供的函数是单个元素,我们将是 returned 可迭代集合。另一方面,如果 flatMap
参数 return 中的函数是一个集合,我们将 return 编辑一个新的 Map。
例如这是您的输入变量:
scala> val numMap = Map(1 -> List(2) , 3 -> List(2,4))
如果我们 return 只有来自 flatMap
函数参数的单个元素,我们会得到 List
scala> numMap.flatMap{case(k,v) => v}
res0: List(2, 2, 4)
或(return单个元素的另一种方式)
scala> numMap.flatMap{case(k,v) => v.map(e => e)}
res1: List(2, 2, 4)
但是,如果我们 return 从 flatMap
中的函数中收集一个集合,我们将得到 Map
。我们在这里 returning 元组 (<element of list>, <key>)
scala> numMap.flatMap{case(k,v) => v.map(e => (e,k))}
res2: Map(2 -> 3, 4 -> 3)
如果我们想要 return 来自 flatMap
函数参数的集合,我们可以使用 case class
并获得 List
:
scala> case class MyCollection(a: Int, b: Int)
scala> numMap.flatMap{case(k,v) => v.map(e => MyCollection(e,k))}
res4: List(MyCollection(2,1), MyCollection(2,3), MyCollection(4,3))