VSh*_*VSh 1 scala for-comprehension scala-collections
我有以下代码:
val dummy = Map(1 -> Map(2 -> 3.0,
4 -> 5.0),
6 -> Map(7 -> 8.0))
val thisIsList = for (x <- dummy; y <- x._2.keys) yield s"(${x._1}, ${y})"
println(thisIsList) // List((1, 2), (1, 4), (6, 7))
val thisIsMap = for (x <- dummy; y <- x._2.keys) yield new Tuple2(x._1, y)
println(thisIsMap) // Map(1 -> 4, 6 -> 7) - this is not what I want
Run Code Online (Sandbox Code Playgroud)
我希望第二个语句产生一个元组列表,但是它返回一个Map。我在这里找到了一个解释说明:生成一个元组序列而不是map来说明为什么返回Map,但是在这种情况下,我仍在努力寻找一种优雅的方法来返回元组列表。
这是因为for编译器将理解语法转换为一系列方法调用的原因。map,flatMap和withFilter的目标是for理解力的排列。这是非常强大且通用的,因为它允许语法与任意类型一起使用。还有更多功能,例如CanBuildFrom 隐式,但本质上将a映射Map到Iterable[Tuple[A, B]]会产生Map[A, B]。签名实际上已过载Map以提供此行为
具体来说,以下是您的原始代码
val thisIsMap = for (x <- dummy; y <- x._2.keys) yield new Tuple2(x._1, y)
println(thisIsMap) // Map(1 -> 4, 6 -> 7) - this is not what I want
Run Code Online (Sandbox Code Playgroud)
翻译看起来像这样
val thisIsMap = dummy.flatMap { x =>
x._2.keys.map { y =>
(x._1, y)
}
}
Run Code Online (Sandbox Code Playgroud)
看到这个小提琴
为了获得所需的列表,我们可以编写
val thisIsMap = (for (x <- dummy; y <- x._2.keys) yield (x._1, y)).toList
Run Code Online (Sandbox Code Playgroud)
但是,如果考虑到我们对for理解的了解,我们可以将其写得更加优雅:
val thisIsMap = for (x <- dummy.toList; y <- x._2.keys) yield (x._1, y)
Run Code Online (Sandbox Code Playgroud)
在上文中,我们通过推断对a的for理解List会产生a ,从而充分利用了混淆原始代码的行为List。
但是,请注意,在理解之后,将源转换为aList与将结果映射转换为a的区别List。
如果我们调用toListsource(dummy)List((1,2), (1,4), (6,7)),则会得到结果,而如果对结果进行调用,则会得到结果,由于List((1,4), (6,7))显而易见的原因,请谨慎选择。
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |