【问题标题】:summing a transformation of a list of numbers in scala在scala中对数字列表的转换求和
【发布时间】:2011-10-11 17:09:26
【问题描述】:

我经常需要对 Scala 中数字列表的转换求和。当然,一种方法是:

list.map(transform(_)).sum

但是,当不需要创建内存时,这会创建内存。另一种方法是折叠列表。

list.foldLeft(0.0) { (total, x) => total + f(x) }

我发现第一个表达式比第二个表达式更容易编写。有没有一种我可以使用的方法,它具有第一种的易用性和第二种的效率?还是我最好编写自己的隐式方法?

list.mapSum(transform(_))

【问题讨论】:

  • 仅相切相关,但如果对 集合 求和变换时要小心,例如:Set(1,2,3).map(_ % 2).sum1,而不是 2。我最近被setOfPlayers.map(_.salary).sum之类的东西咬了...

标签: scala


【解决方案1】:

您可以使用 view 使您的转换器方法(映射、过滤器...)变得懒惰。请参阅here 了解更多信息。

因此,例如,在您的方法名为 transform 的情况下,您可以编写

list.view.map(transform).sum

(请注意,您可以选择省略(_)

【讨论】:

  • 我记得这一点,但一些错误的测试让我确信这让事情变得更慢。今天,在玩了一些之后,view 看起来很棒!
  • @schmmd 在一些琐碎的情况下实现view 会使事情变慢,这可能是默认情况下不自动应用它的原因。我认为这取决于您使用/过滤掉的元素的比例等因素。还有速度!=内存。因此,如果速度很关键,最好的办法可能是尝试并进行基准测试。
  • 在这个例子中我应该只使用一个迭代器。
  • @schmmd 这当然是您只需要处理整个列表或前 n 个元素的选项。视图更加灵活,因为您可以随意多次访问元素。迭代器来自命令式编程并且具有可变状态,因此通常最好在函数式代码中避免使用。
  • 很好理解,但是视图在 scala 中被认为是非常有问题的,以至于很多人都想删除它们,所以我避免使用它们。
【解决方案2】:

这个操作叫做foldMap,你可以在Scalaz中找到它。

list foldMap transform

【讨论】:

  • +1 当我开始使用 scalaz 时,我未来的替代者会非常讨厌我。
  • 正如给定的,这个表达式不会对元素求和,是吗?
  • 进一步详细说明,foldMap 具有以下类型签名:def foldMap[A, M: Monoid](t: F[A], f: A => M): M,因此您的转换必须返回一个 Monoid,因此,有一个“零”和一个 |+|操作,foldMap 将用于累积结果。
  • @Zwirb 在该签名中有两个参数,但我在答案中只看到一个参数。 F[A] 是什么?
  • @LuigiPlinge:你是对的!我引用了 Foldable 特征中的方法 def 而不是 MA 特征中的方法,这是此处实际使用的方法(最终调用 Foldable 中的方法):def foldMap[B](f: A => B)(implicit r: Foldable[M], m: Monoid[B]): B = r.foldMap(value, f),其中@ 987654332@ 是你的原始列表,它被添加到具有 MA 特征的东西中。顺便说一句,这也让我感到困惑:我几乎没有开始在 scalaz 周围找到自己的路......
猜你喜欢
  • 2021-09-20
  • 2017-10-11
  • 1970-01-01
  • 2016-09-19
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 2020-04-24
  • 1970-01-01
相关资源
最近更新 更多