在 Scala 中嵌套 for 推导式是一种好的风格吗?

发布于 2024-11-30 18:46:02 字数 650 浏览 0 评论 0原文

我刚刚发现自己编写了一段如下所示的代码:

  def language(frequencies: Array[String], text: Array[String]) = {
    val allText = text.mkString.replace(" ", "")

    val emaps = for {
      fset <- frequencies
      devs = for {
        i <- 'a' to 'z'
        p = fset.indexOf(i) match {
          case -1 => 0d
          case x  => fset.substring(x + 1, x + 3).toDouble / 100 * allText.size
        }
        a = allText.count(i ==)
        dev = math.pow(p - a, 2)
      } yield dev
    } yield devs.sum

    emaps.min
  }

如您所见,值 emaps 是从字符串数组创建的双精度数组。效果很好。我以前从未见过像这样嵌套的 for-comparatives。可以吗还是我应该以某种方式重构?

I just found myself writing a piece of code that looks like this:

  def language(frequencies: Array[String], text: Array[String]) = {
    val allText = text.mkString.replace(" ", "")

    val emaps = for {
      fset <- frequencies
      devs = for {
        i <- 'a' to 'z'
        p = fset.indexOf(i) match {
          case -1 => 0d
          case x  => fset.substring(x + 1, x + 3).toDouble / 100 * allText.size
        }
        a = allText.count(i ==)
        dev = math.pow(p - a, 2)
      } yield dev
    } yield devs.sum

    emaps.min
  }

As you can see, the value emaps is an array of Doubles created from an array of Strings. It works fine. I just haven't seen for-comprehensions nested like this before. Is it OK or should I refactor somehow?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哭了丶谁疼 2024-12-07 18:46:02

通常,使用 map 和朋友比在 for 构造的循环部分编写长代码块更标准。由于 allText 不依赖于频率,因此您可以在开始时执行一次:(

val lcounts = 'a' to 'z' map {i => i -> allText.count(i==)} toMap
val emaps = frequencies.map { fset =>
  val devs = 'a' to 'z' map { i =>
    val p = fset.indexOf(i) match {
      case -1 => 0d
      case x  => fset.substring(x+1, x+3).toDouble / 100 * allText.size
    }
    math.pow(p - lcounts(i), 2)
  }
  devs.sum
}

另外,您确定要对负值进行平方吗,即 allText.count(i==) 不为零,但 fset.indexOf (i) 是-1?这看起来很奇怪。)

It's generally more standard to use map and friends than to write long blocks of code in the looping part of the for construct. And since allText doesn't depend on the frequencies, you can do that once at the beginning:

val lcounts = 'a' to 'z' map {i => i -> allText.count(i==)} toMap
val emaps = frequencies.map { fset =>
  val devs = 'a' to 'z' map { i =>
    val p = fset.indexOf(i) match {
      case -1 => 0d
      case x  => fset.substring(x+1, x+3).toDouble / 100 * allText.size
    }
    math.pow(p - lcounts(i), 2)
  }
  devs.sum
}

(Also, are you sure you want to square negative values, i.e. where allText.count(i==) is nonzero, but fset.indexOf(i) is -1? That seems strange.)

記柔刀 2024-12-07 18:46:02

一旦我使用 match 语句或其他简单的、持续的 if/else 语句,我就会在那里使用一种方法。通过良好的命名,代码将变得更清晰易读(IMO)。

As soon as I use a match statement or something other then simple , sustinct if/ else I would use a method there. With good naming the code would become clearer to read IMO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文