我想在功能上写它,我能做的最好的是:
list.zipWithIndex.filter((tt:Tuple2[Thing,Int])=>(tt._2%3==0)).unzip._1
获取元素0,3,6,...
是否有更易读的Scala成语?
答案 0 :(得分:12)
如果效率不是问题,您可以执行以下操作:
list.grouped(3).map(_.head)
请注意,这会构建中间列表。
或者你可以使用for-comprehension:
for {
(x,i) <- list zipWithIndex
if i % 3 == 0
} yield x
这当然与原始解决方案几乎完全相同,只是用不同的方式编写。
我的最后一个替代方案是在压缩列表中使用collect:
list.zipWithIndex.collect {
case (x,i) if i % 3 == 0 => x
}
答案 1 :(得分:5)
不太清楚,但仍然:
xs.indices.collect { case i if i % 3 == 0 => xs(i) }
答案 2 :(得分: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
}
答案 3 :(得分:1)
Clojure有一个take-nth
函数可以满足您的需求,但我很惊讶地发现Scala中没有等效的方法。您可以根据Clojure代码编写类似的递归解决方案,或者您可以阅读此博客文章:
Scala collections: Filtering each n-th element
作者实际上在最后有一个很好的图表,显示了他的每个解决方案的相对表现。
答案 4 :(得分:0)
我会像Octave数学程序那样做。
val indices = 0 until n by 3 // Range 0,3,6,9 ...
然后我需要一些方法来从集合中选择索引。显然我必须有一个随机访问O(1)的集合。与Array
或Vector
一样。例如,我在这里使用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)
答案 5 :(得分: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)