【问题标题】:Scala: Iterating with access to multiple elementsScala:通过访问多个元素进行迭代
【发布时间】:2019-08-08 10:20:33
【问题描述】:

我有一个迭代器,它以某种排序顺序包含我需要的所有数据。我想对每个数据元素执行一些操作,考虑到迭代器中的前后元素。 IE。我有一个函数,给定 n 个元素,将参数 f(iter(k-1), iter(k), iter(k+1)) 用于 0 < k < n-1

当然,我不能只遍历迭代器,因为我在调用函数时无法访问 k + 1 元素。

我可以把整个事情做一个列表并使用索引,但这会很不雅。 Scala 访问这些值的方式是什么?我可以以某种方式将迭代器与自身和偏移量组合在一起吗?

【问题讨论】:

  • Scala 集合具有sliding 方法。迭代器也应该有它们,但我不确定这个。
  • 您可能可以使用列表中的 zipWithIndex 方法。但是,创建元组是一项昂贵的操作,您可以使用视图来代替。请参考stackoverflow.com/a/6833653/7803797
  • 你可以试试这个方法:stackoverflow.com/questions/53378160/…
  • 如果迭代器的元素少于三个,预期的行为是什么?

标签: scala iterator


【解决方案1】:

@ygor 的评论是正确的。

yourIterator.sliding(3)
            .collect{ case Seq(prev, current, next) =>
              //proceed accordingly
            }

请注意,代码不知道哪个是最终的 3 集合。 yourIterator 中的最后一个元素永远不会是 current

【讨论】:

  • 如果迭代器中的元素数量少于 3,这将失败。我在这个上烧了自己几次。
【解决方案2】:

我会考虑使用方法sliding 来满足您的需求。假设函数f 返回与迭代器元素类型相同的类型。以下方法 sliding3Iter 将从提供的迭代器中提供一个包含 3 个元素的滑动窗口,以作为其参数的函数 f

def sliding3Iter[T](it: Iterator[T], f: (T, T, T) => T): Iterator[T] =
  it.sliding(3).
    collect{ case ls if ls.size == 3 => f(ls(0), ls(1), ls(2)) }

例如:

val f = (i: Int, j: Int, k: Int) => i + j + k

val it = (0 to 10).toIterator

sliding3Iter(it, f).toList
// res1: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27)

【讨论】:

  • 我觉得这两个答案可以结合起来提供更好的答案。首先,collect 比 map 好,因为它涵盖了少于 3 个元素的迭代器。此外,collect 可以直接对 3 个元素的 seq 进行模式匹配,就像其他答案一样。
猜你喜欢
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多