8

我想在功能上编写它,而我能做的最好的事情是:

list.zipWithIndex.filter((tt:Tuple2[Thing,Int])=>(tt._2%3==0)).unzip._1

获取元素 0, 3, 6,...

有没有更易读的 Scala 习语呢?

4

6 回答 6

18

如果效率不是问题,您可以执行以下操作:

list.grouped(3).map(_.head)

请注意,这会构建中间列表。

或者,您可以使用理解:

for {
  (x,i) <- list zipWithIndex
  if i % 3 == 0
} yield x

这当然与您的原始解决方案几乎相同,只是编写方式不同。

我的最后一个选择是在压缩列表上使用 collect :

list.zipWithIndex.collect {
  case (x,i) if i % 3 == 0 => x
}
于 2013-09-15T17:37:49.330 回答
7

不是很清楚,但仍然:

xs.indices.collect { case i if i % 3 == 0 => xs(i) }
于 2013-09-15T16:28:00.503 回答
5

一个不错的实用解决方案,无需创建临时向量、列表等:

def everyNth[T](xs: List[T], n:Int): List[T] = xs match {
  case hd::tl => hd::everyNth(tl.drop(n-1), n)
  case Nil => Nil
}
于 2013-09-17T14:29:28.127 回答
1

Clojure 有一个take-nth功能可以满足您的需求,但我惊讶地发现 Scala 中没有等效的方法。您可以根据 Clojure 代码编写一个类似的递归解决方案,或者您可以阅读这篇博文:

Scala 集合:过滤每个第 n 个元素

作者实际上在最后有一个很好的图表,显示了他的每个解决方案的相对性能。

于 2013-09-15T16:28:12.200 回答
0

啊,这个怎么样?

val l = List(10,9,8,7,6,5,4,3,2,1,0)
for (i <- (0 to l.size - 1 by 3).toList) yield l(i)
//res0: List[Int] = List(10, 7, 4, 1)

这可以通过

def seqByN[A](xs: Seq[A], n: Int): Seq[A] = for (i <- 0 to xs.size - 1 by n) yield xs(i)

scala> seqByN(List(10,9,8,7,6,5,4,3,2,1,0), 3)
res1: Seq[Int] = Vector(10,7,4,1)

scala> seqByN(List(10,9,8,7,6,5,4,3,2,1,0), 3).toList
res2: Seq[Int] = List(10,7,4,1)

scala> seqByN(List[Int](), 3)
res1: Seq[Int] = Vector()

但是,功能是指仅使用各种 List 组合器功能吗?否则,Streams 的功能是否足够?

def fromByN[A](xs: List[A], n: Int): Stream[A] = if (xs.isEmpty) Stream.empty else
  xs.head #:: fromByN(xs drop n, n)

scala> fromByN(List(10,9,8,7,6,5,4,3,2,1,0), 3).toList
res17: List[Int] = List(10, 7, 4, 1)
于 2013-09-16T15:42:44.233 回答
0

我会像在 Octave 数学程序中那样做。

val indices = 0 until n by 3  // Range 0,3,6,9 ...

然后我需要一些方法来从集合中选择索引。显然我必须有一个随机访问 O(1) 的集合。喜欢ArrayVector。例如这里我使用Vector. 要将访问包装到一个不错的 DSL 中,我会添加一个隐式类:

implicit class VectorEnrichedWithIndices[T](v:Vector[T]) {
  def apply(indices:TraversableOnce[Int]):Vector[T] = {
    // some implementation 
    indices.toVector.map(v)
  }
}

用法如下所示:

val vector = list.toVector
val every3rdElement = vector(0 until vector.size by 3)
于 2013-09-15T19:03:46.140 回答