假设我使用各种map
和/或flatMap
s的序列来生成一系列集合。是否可以从任何这些方法中访问有关“当前”集合的信息?例如,在不知道前一个map
或flatMap
中使用的函数的任何具体内容的情况下,如果不使用任何中间声明,我如何获得最大值(或长度,或第一个元素,最后map
行动的集合的哪一部分?
List(1, 2, 3)
.flatMap(x => f(x) /* some unknown function */)
.map(x => x + ??? /* what is the max element of the collection? */)
编辑以澄清:
在示例中,我不是在寻找初始List
的最大值(或其他值)。在flatMap
被应用后,我正在寻找最大的收藏。
通过“不使用任何中间声明”,我的意思是我不想在途中使用任何临时集合到最终结果。因此,下面的史蒂夫沃尔德曼的例子虽然给出了理想的结果,但并不是我所追求的。 (我包括这种情况主要是出于审美原因。)
编辑以澄清,第2部分:
理想的解决方案是一些神奇的关键词或语法糖,让我参考当前的集合:
List(1, 2, 3)
.flatMap(x => f(x))
.map(x => x + theCurrentList.max)
然而,我准备接受这样的事实,即这根本不可能。
答案 0 :(得分:2)
也许只是将列表定义为val
,您可以命名吗?我不知道map(...)
或flatMap(...)
内置的任何设施都会有所帮助。
val myList = List(1, 2, 3)
myList
.flatMap(x => f(x) /* some unknown function */)
.map(x => x + myList.max /* what is the max element of the List? */)
更新:至少通过这种方法,如果您有多个转换并希望查看转换后的版本,则必须将其命名。你可以逃脱
val myList = List(1, 2, 3).flatMap(x => f(x) /* some unknown function */)
myList.map(x => x + myList.max /* what is the max element of the List? */)
或者,如果会有多次转换,请养成命名阶段的习惯。
val rawList = List(1, 2, 3)
val smordified = rawList.flatMap(x => f(x) /* some unknown function */)
val maxified = smordified.map(x => x + smordified.max /* what is the max element of the List? */)
maxified
更新2 :即使使用异类型,也可以在REPL中观察它:
scala> def f( x : Int ) : Vector[Double] = Vector(x * math.random, x * math.random )
f: (x: Int)Vector[Double]
scala> val rawList = List(1, 2, 3)
rawList: List[Int] = List(1, 2, 3)
scala> val smordified = rawList.flatMap(x => f(x) /* some unknown function */)
smordified: List[Double] = List(0.40730853571901315, 0.15151641399798665, 1.5305929709857609, 0.35211231420067435, 0.644241939254793, 0.15530230501048903)
scala> val maxified = smordified.map(x => x + smordified.max /* what is the max element of the List? */)
maxified: List[Double] = List(1.937901506704774, 1.6821093849837476, 3.0611859419715217, 1.8827052851864352, 2.1748349102405538, 1.6858952759962498)
scala> maxified
res3: List[Double] = List(1.937901506704774, 1.6821093849837476, 3.0611859419715217, 1.8827052851864352, 2.1748349102405538, 1.6858952759962498)
答案 1 :(得分:2)
可能,但不是很漂亮,如果你出于“审美原因”这样做,也不太可能是你想要的东西。
import scala.math.max
def f(x: Int): Seq[Int] = ???
List(1, 2, 3).
flatMap(x => f(x) /* some unknown function */).
foldRight((List[Int](),List[Int]())) {
case (x, (xs, Nil)) => ((x :: xs), List.fill(xs.size + 1)(x))
case (x, (xs, xMax :: _)) => ((x :: xs), List.fill(xs.size + 1)(max(x, xMax)))
}.
zipped.
map {
case (x, xMax) => x + xMax
}
// Or alternately, a slightly more efficient version using Streams.
List(1, 2, 3).
flatMap(x => f(x) /* some unknown function */).
foldRight((List[Int](),Stream[Int]())) {
case (x, (xs, Stream())) =>
((x :: xs), Stream.continually(x))
case (x, (xs, curXMax #:: _)) =>
val newXMax = max(x, curXMax)
((x :: xs), Stream.continually(newXMax))
}.
zipped.
map {
case (x, xMax) => x + xMax
}
说真的,我只是接受了这个,看看能否做到。虽然代码没有像我预期的那样糟糕,但我仍然认为它不是特别易读。我不鼓励使用类似于Steve Waldman's answer的东西。有时,仅仅引入一个val
更好,而不是对它有教条。