【问题标题】:Scala filter collection by future result按未来结果收集 Scala 过滤器
【发布时间】:2018-02-03 22:34:00
【问题描述】:

我有一个名为 Source 的类,它有惰性 val isValid,它会进行一些需要时间的网络检查。我已经让它返回 Future[Boolean] 所以它不会阻塞主线程:

lazy val isValid: Future[Boolean] = doSomeChecks()

现在,我想检查几个来源并丢弃无效的来源。
这是一些伪代码:

val sources = Seq(Source1, Source2,...)
val validOnes: Seq[Source] = sources.filter(_.isValid)

我正在考虑某种方法,该方法将从 isValid 返回的 Future[Boolean] 转换为在验证检查完成后将使用整个 Source 对象解析的其他 Future。

最好的方法是什么?

【问题讨论】:

    标签: scala future


    【解决方案1】:

    无需从isValid 返回Source 本身。只需将源本身附加到isValid 请求的每个结果。 一旦有有效性检查的结果,过滤那些来源 是有效的,并丢弃validity-boolean:

    val sources: Seq[Source] = ...
    
    val validSources: Future[Seq[Source]] = (for {
      checkedSources <- Future.sequence(
        sources.map(s => s.isValid.map(b => (s, b)))
      )
    } yield checkedSources.filter(_._2).map(_._1))
    

    在这里,s.isValid 返回一个Future[Boolean]。这个未来与b =&gt; (s, b) 映射,因此s.isValid.map(b =&gt; (s, b))Future[(Source, Boolean)]Future.sequence 将一堆期货转换成一个序列的单一期货。一旦序列被计算出来,它可以被第二个分量过滤,然后第二个分量可以被丢弃。

    我不确定这是否是“最好”的方法,因为我不清楚有效性检查保持足够“新鲜”的时间有多长:很可能是isValid 结果的一半当所有结果都收集到checkedSources 序列中时,检查已经过时了。


    编辑(1):更短:

    val validSources: Future[Seq[Source]] = 
      Future.sequence(sources.map(_.isValid)).map {
        bs => (sources zip bs).filter(_._2).map(_._1)
      }
    

    这应该也可以。

    (未经编译器检查的代码,我脑中的粗略草图;如果您想要一个可编译的解决方案,请提供最小的可编译示例)

    【讨论】:

    • 谢谢,只是想要一个想法,不需要提供工作代码。我只是想知道是否有比将其压缩成元组更清洁的方法。
    猜你喜欢
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 2012-10-06
    • 2021-11-26
    • 1970-01-01
    • 2016-03-02
    • 2018-08-31
    相关资源
    最近更新 更多