【问题标题】:Return second string if first is empty?如果第一个为空,则返回第二个字符串?
【发布时间】:2014-08-20 17:00:34
【问题描述】:

这是我自己写的一个成语。

def chooseName(nameFinder: NameFinder) = {
  if(nameFinder.getReliableName.isEmpty) nameFinder.getReliableName
  else nameFinder.secondBestChoice
}

为了避免在nameFinder 上调用getReliableName() 两次,我添加了使我的方法看起来不那么优雅的代码。

def chooseName(nameFinder: NameFinder) = {
  val reliableName = nameFinder.getReliableName()
  val secondBestChoice = nameFinder.getSecondBestChoice()
  if(reliableName.isEmpty) reliableName
  else secondBestChoice
}

这感觉很脏,因为我使用vals 创建了不必要的状态,除了防止重复的方法调用之外没有其他原因。 Scala 教会了我,每当我感到肮脏时,几乎总有更好的方法。

有没有更优雅的写法?

Here's two Strings, return whichever isn't empty while favoring the first

【问题讨论】:

  • 我知道你可能以前听说过这个,但是对方法调用进行优化是相当极端的。
  • 可能是数据库调用或其他什么。

标签: scala


【解决方案1】:

当然,没有必要总是打电话给getSecondBestChoice。就个人而言,我发现更改后的代码没有任何不雅之处 - 很清楚它的作用,没有可变状态。其他答案似乎过于复杂,只是为了避免使用val

def chooseName(nameFinder: NameFinder) = {
  val reliableName = nameFinder.getReliableName()

  if(reliableName.isEmpty) reliableName
  else nameFinder.getSecondBestChoice()
}

如果你真的想避免使用 val,这里有另一个变体(如果有两个以上的替代方案,可以很好地概括)

List(nameFinder.getReliableName(), nameFinder.getSecondBestChoice()).find(_.nonEmpty).get

(或getOrElse(lastResort),如果列表中的所有内容也可能为空)

【讨论】:

    【解决方案2】:

    这是一种使用Option 的方法。它并没有那么漂亮,但所有东西都只调用一次。这假设您想要一个 String 作为结果,并且不关心第二个字符串是否为空。

    Some(nameFinder.getReliableName)
        .filter(_.nonEmpty)
        .getOrElse(nameFinder.secondBestChoice)
    

    【讨论】:

    • 我更喜欢 Option(nameFinder.getReliableName),如果包装 Java 类型,它会将 null 处理为 None
    • 但是您调用的是 Some.apply、Some.filter、Some.getOrElse。如果他的目标是尽可能多地避免方法调用,那就更糟了。
    • @monkjack 我认为关键是要避免多次调用nameFinder.getReliableName 以消除冗余。
    • 如果getReliableName 是一个相当复杂的方法,那么这段代码会更好。没有任何val 也没有更多的方法调用,我认为这个问题很好……没有它们我们能做到吗?
    【解决方案3】:
    Option(namefinder.getReliableName) // transforms a potential null into None
    .filter(_.trim.nonEmpty) // "" is None, but also "   "
    .getOrElse(nameFinder.secondBestChoice)
    

    或者更好,如果您可以修改getReliableName 以返回Option[String]

    def chooseName(nameFinder: NameFinder): String =
      namefinder.getReliableName getOrElse nameFinder.secondBestChoice
    

    最后,如果secondBestChoice 也可能失败(假设它返回Option[String]):

    def chooseName(nameFinder: NameFinder): Option[String] =
      namefinder.getReliableName orElse nameFinder.secondBestChoice
    

    【讨论】:

      【解决方案4】:

      如果您不止一次需要它:

      scala> implicit class `nonempty or else`(val s: String) extends AnyVal {
           | def nonEmptyOrElse(other: => String) = if (s.isEmpty) other else s }
      defined class nonempty
      
      scala> "abc" nonEmptyOrElse "def"
      res2: String = abc
      
      scala> "" nonEmptyOrElse "def"
      res3: String = def
      

      【讨论】:

      • 只需注意null 的情况。如果getReliableName 可以返回null(可能是java 代码),那么getReliableName.nonEmptyOrElse 可能会很危险。
      • @GabrielePetronella 是的,但这不是用例;而且很容易添加,所以,有点跑题了。但无论如何我都不反对 Option:stackoverflow.com/a/23126703/1296806
      【解决方案5】:

      使用以下模式匹配可以提供更整洁的代码,

      def chooseName(nameFinder: NameFinder) = {
        nameFinder.getReliableName match {
          case r if r.isEmpty => r
          case _              => nameFinder.secondBestChoice
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-10-10
        • 1970-01-01
        • 1970-01-01
        • 2018-07-18
        • 2011-08-17
        • 2017-12-11
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多