在Scala中进行运算符链接时访问以前的输出
如何访问结果输出值以执行后续操作,例如:在Scala中进行运算符链接时访问以前的输出,scala,functional-programming,Scala,Functional Programming,如何访问结果输出值以执行后续操作,例如: scala> List(1,4,3,4,4,5,6,7) res0: List[Int] = List(1, 4, 3, 4, 4, 5, 6, 7) scala> res0.removeDuplicates.slice(0, ???.size -2) scala> val ls = List(1,1,2,2,3,3,4,4) ls: List[Int] = List(1, 1, 2, 2, 3, 3, 4, 4) scala&g
scala> List(1,4,3,4,4,5,6,7)
res0: List[Int] = List(1, 4, 3, 4, 4, 5, 6, 7)
scala> res0.removeDuplicates.slice(0, ???.size -2)
scala> val ls = List(1,1,2,2,3,3,4,4)
ls: List[Int] = List(1, 1, 2, 2, 3, 3, 4, 4)
scala> :paste
// Entering paste mode (ctrl-D to finish)
for {
ls1 <- Option(ls.map(_ * 2))
ls2 = ls1.map(_ + ls1.size)
ls3 = ls2.filter(_ < ls1.size + ls2.size)
} yield ls3.sum
// Exiting paste mode, now interpreting.
res15: Option[Int] = Some(72)
在上面的一行中,我需要在删除重复项后执行切片操作。为此,我将介绍如何访问.removeDuplicate()
的输出,以便使用它查找切片操作的大小
我需要在一个步骤中执行此操作。不是在多个步骤中,例如:
scala> res0.removeDuplicates
res1: List[Int] = List(1, 4, 3, 5, 6, 7)
scala> res1.slice(0, res1.size -2)
res2: List[Int] = List(1, 4, 3, 5)
我希望在最终操作中访问中间结果removeDuplicates()
只是一个例子
list.op1().op2().op3().finalop()
这里我想访问:op1
的输出,op2
,op3
在finalop中如果使用dropRight
,则无需知道长度:
scala> val a = List(1,4,3,4,4,5,6,7)
a: List[Int] = List(1, 4, 3, 4, 4, 5, 6, 7)
scala> a.dropRight(2)
res0: List[Int] = List(1, 4, 3, 4, 4, 5)
这样做:res0.removeDuplicates.dropRight(2)
如果在一个函数中确实需要它,您可以编写一个自定义的foldLeft
,如下所示:
var count = 0
val found = new HashSet()
res0.foldLeft(List[Int]()) { (z, i) =>
if(!found.contains(i)){
if(count < 4){
z :+ i
found += i
count += 1
}
}
}
var计数=0
val found=new HashSet()
res0.foldLeft(List[Int]()){(z,i)=>
如果(!found.contains(i)){
如果(计数<4){
z:+i
发现+=i
计数+=1
}
}
}
然而,我并没有看到像在res0.removeDuplicates.slice中那样链接调用的问题。函数式编程的一个好处是,我们的编译器可以在这样的情况下进行优化,在这种情况下,我们只需要某个特定的行为,而不想指定实现。包装到选项中可能是一个选项(没有双关语):
您可以使包裹零件隐式化,使其更美观:
object Tapper {
implicit class Tapped[T] extends AnyVal(val v: T) {
def tap[R](f: T => R) = f(v)
}
}
import Tapper._
val finalResult = foo
.tap(f => f.op1(f.stuff))
.tap(f => f.op2(f.stuff))
.tap(f => f.finalOp(f.stuff))
您希望通过一系列转换来处理一些数据:someData->op1->op2->op3->finalOp。但是,在op3中,您希望能够访问op1中完成的处理的中间结果。这里的关键是将下游需要的所有信息传递给处理链中的下一个函数
假设您的输入是xs:Seq[String]
,op1的类型是(xs:Seq[String])=>Seq[String]
。您希望修改op1以返回案例类ResultWrapper(originalInputLength:Int,deduplicatededitems:Seq[String],somethingNeededInOp5:SomeType)
。如果你所有的行动都将其他行动所需要的东西传递下去,你就会得到你所需要的。这不是很优雅,因为您的操作之间存在耦合:上游需要保存下游需要的信息。在这一点上,它们不再是真正的“不同的操作”
您可以做的一件事是使用Map[a,B]作为“结果包装器”。通过这种方式,ops之间的耦合更少,但类型安全性也更低。使用进行理解可以以非常可读的方式编写操作,并能够访问中间结果:
val res = for {
ls1 <- Option(list.op1)
ls2 = ls1.op2() // Possible to access list, ls1
ls3 = ls2.op3() // Possible to access list, ls1, ls2
} yield ls4.finalOp() // Possible to access list, ls1, ls2, ls3
val res=for{
ls1 val ls=列表(1,1,2,2,3,3,4,4)
ls:List[Int]=List(1,1,2,2,3,3,4,4)
scala>:粘贴
//进入粘贴模式(按ctrl-D键完成)
为了{
ls1 Scala的标准库提供了,因此删除的复制可能是不必要的。例如:List(1,4,3,4,4,5,6,7)。distinct
=List[Int]=List(1,4,3,5,6,7)
您想访问所有中间结果吗?或者op3
的结果足够了吗?我需要所有的结果。请注意,如果您知道只访问op3(即上一个),那么在最后的操作中访问中间结果会很有帮助。removeDuplicates()
只是一个示例。list.op1().op2().op3().finalop()
这里我想访问:finalop
@codestward中的op1
、op2
、op3
的输出您在这个评论中要求的与您的问题完全不同。您想在当前方法调用中一般能够访问以前的结果吗?不,removeDuplicates()
是一个操作(op1,op2,…)的示例。我只是对其进行了概括。您可以通过将op1()中的信息保存到从op1传递到op2的ResultRapper中来实现这一点。因此,不要只传递Result;传递ResultRapper,它包含您需要的中间数据。我使用了RemovedUpplicates()
仅作为一个示例。基本上,我希望在当前操作中使用所有先前操作的输出。如果您希望在最后一步访问每个步骤的输出,您可能还需要一个flatTap
;)
scala> val ls = List(1,1,2,2,3,3,4,4)
ls: List[Int] = List(1, 1, 2, 2, 3, 3, 4, 4)
scala> :paste
// Entering paste mode (ctrl-D to finish)
for {
ls1 <- Option(ls.map(_ * 2))
ls2 = ls1.map(_ + ls1.size)
ls3 = ls2.filter(_ < ls1.size + ls2.size)
} yield ls3.sum
// Exiting paste mode, now interpreting.
res15: Option[Int] = Some(72)