当某些条件为真时,Scala foldLeft [英] Scala foldLeft while some conditions are true

查看:65
本文介绍了当某些条件为真时,Scala foldLeft的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Scala中模拟以下行为?也就是说,在满足蓄能器上的某些特定条件时,请保持折叠状态.

How to emulate following behavior in Scala? i.e. keep folding while some certain conditions on the accumulator are met.

def foldLeftWhile[B](z: B, p: B => Boolean)(op: (B, A) => B): B

例如

scala> val seq = Seq(1, 2, 3, 4)
seq: Seq[Int] = List(1, 2, 3, 4)
scala> seq.foldLeftWhile(0, _ < 3) { (acc, e) => acc + e }
res0: Int = 1
scala> seq.foldLeftWhile(0, _ < 7) { (acc, e) => acc + e }
res1: Int = 6

更新:

基于@Dima的答案,我意识到我的意图有些副作用.所以我使它与 takeWhile 同步,即,如果谓词不匹配,则不会前进.并添加更多示例以使其更清晰.(注意:不适用于 Iterator s)

Based on @Dima answer, I realized that my intention was a little bit side-effectful. So I made it synchronized with takeWhile, i.e. there would be no advancement if the predicate does not match. And add some more examples to make it clearer. (Note: that will not work with Iterators)

推荐答案

首先,请注意您的示例似乎是错误的.如果我正确理解您的描述,结果应该是 1 (满足谓词 _< 3 的最后一个值),而不是 6

First, note that your example seems wrong. If I understand correctly what you describe, the result should be 1 (the last value on which the predicate _ < 3 was satisfied), not 6

最简单的方法是使用 return 语句,该语句在scala中非常皱眉,但是我想,出于完整性考虑,我会提到它.

The simplest way to do this is using a return statement, which is very frowned upon in scala, but I thought, I'd mention it for the sake of completeness.

def foldLeftWhile[A, B](seq: Seq[A], z: B, p: B => Boolean)(op: (B, A) => B): B = foldLeft(z) { case (b, a) => 
   val result = op(b, a) 
   if(!p(result)) return b
   result
}

由于我们要避免使用return,因此有可能使用 scanLeft :

Since we want to avoid using return, scanLeft might be a possibility:

seq.toStream.scanLeft(z)(op).takeWhile(p).last

这有点浪费,因为它会累积所有(匹配的)结果.您可以使用 iterator 而不是 toStream 来避免这种情况,但是出于某些原因, Iterator 没有 .last ,因此,您必须明确地额外扫描一次:

This is a little wasteful, because it accumulates all (matching) results. You could use iterator instead of toStream to avoid that, but Iterator does not have .last for some reason, so, you'd have to scan through it an extra time explicitly:

 seq.iterator.scanLeft(z)(op).takeWhile(p).foldLeft(z) { case (_, b) => b }

这篇关于当某些条件为真时,Scala foldLeft的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆