Scala filter on a list by index
Solution 1
If efficiency is not an issue, you could do the following:
list.grouped(3).map(_.head)
Note that this constructs intermediate lists.
Alternatively you can use a for-comprehension:
for {
(x,i) <- list zipWithIndex
if i % 3 == 0
} yield x
This is of course almost identical to your original solution, just written differently.
My last alternative for you is the use of collect on the zipped list:
list.zipWithIndex.collect {
case (x,i) if i % 3 == 0 => x
}
Solution 2
Not much clear, but still:
xs.indices.collect { case i if i % 3 == 0 => xs(i) }
Solution 3
A nice, functional solution, without creating temporary vectors, lists, and so on:
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
}
Solution 4
Clojure has a take-nth
function that does what you want, but I was surprised to find that there's not an equivalent method in Scala. You could code up a similar recursive solution based off the Clojure code, or you could read this blog post:
Scala collections: Filtering each n-th element
The author actually has a nice graph at the end showing the relative performance of each of his solutions.
user833970
Updated on June 04, 2022Comments
-
user833970 almost 2 years
I wanted to write it functionally, and the best I could do was:
list.zipWithIndex.filter((tt:Tuple2[Thing,Int])=>(tt._2%3==0)).unzip._1
to get elements 0, 3, 6,...
Is there a more readable Scala idiom for this?
-
gzm0 over 10 yearsYou might want to add that indexed access should be
O(1)
, otherwise this will not performO(n)
.