繁体   English   中英

拉链迭代Scala中的列表

[英]Zipper to iterate over list in Scala

这是我先前问题的跟进。 我可以使用迭代器, foldzipforeach和其他迭代器在Scala中的列表上进行迭代。 现在,我想知道是否存在最适合使用Zipper用例。 假设我需要没有并发的只读访问权限。

您能举一个这样的例子,并解释为什么Zipper是最佳选择吗?

拉链的许多优点之一就是它们有一个comonad实例,这使我们可以非常优雅地解决一类问题。

这是一个简单的例子。 假设我们有一个数字序列,我们想用指数移动平均值进行简单的平滑,其中列表中每个位置的新值是当前值和所有其他值的平均值,但是较远的邻居贡献较少。

强制性地计算这并不是一件非常困难的事情,但是如果我们使用拉链和共电结合,则距离单线也不太远:

import scalaz._, Scalaz._

val weights = Stream.from(1).map(1.0 / math.pow(2, _))

def sumNeighborWeights(neighbors: Stream[Double]) =
  neighbors.fzipWith(weights)(_ * _).sum

def smooth(data: NonEmptyList[Double]) = data.toZipper.cobind { z =>
  (z.focus + sumNeighborWeights(z.lefts) + sumNeighborWeights(z.rights)) / 3
}

现在,如果我们写:

val result = smooth(NonEmptyList[Double](0, 0, 0, 1, 0, 0, 0)).toList

我们在道德上等同于:

List(1 / 24, 1 / 12, 1 / 6, 1 / 3, 1 / 6, 1 / 12, 1 / 24)

给定我们如何定义问题,这就是我们想要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM