【问题标题】:Idiomatic Scala: Mapping over option depending on condition惯用的Scala:根据条件映射选项
【发布时间】:2017-01-27 23:57:13
【问题描述】:

我有两个vals,一个condition 和一个option。请注意,condition 是一个简单的布尔值,不取决于选项的值。

如果condition 成立,我想映射选项以将其转换为结果值。在所有其他情况下,我想返回 defaultResult。

这行得通并且可读性很好,但我不喜欢defaultResult的重复:

val result = if (condition) {
  option.map(valueToResult).getOrElse(defaultResult)
} else {
  defaultResult
}

我的第二种方法没有重复,但我不喜欢过滤器被滥用于实际上不依赖于选项值的东西的事实:

val result = option.filter(_ => condition).map(valueToResult).getOrElse(defaultResult)

在 Scala 中有什么更惯用或更好的方法?

【问题讨论】:

  • 为什么你觉得filter被滥用了?因为它基于与Option[T] 的基础值无关的外部值进行过滤?没有规定“仅使用filter 过滤掉底层Option[T] 的属性”。我会选择第二个。
  • 没错。我知道没有规则,这只是个人(不)口味。
  • 我明白你的意思。我有时也会有这种感觉。请参阅我的答案以获取可能的替代解决方案。
  • 对Boolean - existentialtype.wordpress.com/2011/03/15/boolean-blindness 的错误选择的旁注。

标签: scala


【解决方案1】:

你可以使用Option.collect:

返回一个scala.Some,其中包含将pf应用于此的结果 scala.Option 的包含值,如果此选项为非空且 pf 为 为该值定义。

val result = option.collect {
  case x if condition => valueToResult(x)
}.getOrElse(defaultResult)

【讨论】:

  • @YuvalItzchakov 为什么不直接使用option match {} 而不是option.collect {}?
  • @SarveshKumarSingh 因为她想根据外部条件应用过滤器。这只是其中一种方式。
  • option match 其实也很不错。我将其发布为仅用于文档的答案。
【解决方案2】:
val result = option match {
  case Some(value) if condition => valueToResult(value)
  case _ => defaultResult
}

【讨论】:

    【解决方案3】:
    val result = (for (v<-option if condition) yield valueToResult(v)).getOrElse(defaultResult)
    

    【讨论】:

      【解决方案4】:
      option.foldLeft(defaultResult)((d,x) => if (condition) valueToResult(x) else d)
      

      【讨论】:

        【解决方案5】:
        val result = (condition match {
          case true => option.map(valueToResult)
          case false => None
        }).getOrElse(defaultResult)
        

        【讨论】:

          猜你喜欢
          • 2018-12-19
          • 1970-01-01
          • 2014-04-24
          • 2021-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多