How do I return multiple elements from a list given their indices?
Let's say I have a list. If I want to return something in the index of this list, I can just pass the index val, index. Thus.
val list = List(1, 2, 3)
list(0) //Int = 1
But what if I want elements from multiple indices in this list? I want to be able to do this ... list(0, 1)
and get a set of elements at those indices.
It's insanely simple in Ruby. Anyone have any suggestions?
source to share
You can flip the logic so that for each index, you get the index, you get the element at that index. Since you are using the apply
on method List
, there are several shorthand expressions for this logic:
val indices = List(0, 1)
indices.map(index => list.apply(index))
indices.map(index => list(index))
indices.map(list(_))
indices.map(list)
indices map list
It's worth noting that since this is all maps
on indices
, the resulting collection will generally be of the same type as indices
, rather than List
:
val list = Array(1, 2, 3)
val indices = List(0, 1)
indices map list //List(1, 2), instead of Array(1, 2)
This might be an unwanted property here. One solution to this is to use breakOut
(in scala.collection
):
val newList: Array[Int] = indices.map(list)(breakOut)
You can read more about breakOut here . The following solutions also support collection type List
when possible, performing operations on List
instead indeces
:
If you are looking for a contiguous range of a list, you can use slice
:
list.slice(1, 2) //List(2)
You can also use drop
and take
(and versions dropRight
, takeRight
) for a similar effect:
list.drop(1).take(1)
For more complex versions of this type of filtering, you might be interested in a method zipWithIndex
that allows you to express arbitrary logic by index:
list.zipWithIndex.collect {
case(el, index) if indices.contains(index) /* any other logic */ => el
}
source to share
The answer from @Ben is in place.
However, if you want to use the descriptive syntax, list(0, 1)
then Scala allows you to do so through implicit conversions:
implicit class MultiIndexList[A](list: List[A]){
def apply(indices: Int *) = indices.map(list)
}
Assuming you are working on the REPL:
val list = List(1,2,3)
list(1,2)
res1: Seq[Int] = ArrayBuffer(2, 3)
list(0,2)
res2: Seq[Int] = ArrayBuffer(1, 3)
source to share
If you're looking for the Ruby Array#slice
(aka Array#[]
) equivalent , there are two:
- the Ruby equivalent
Array#[](index)
as you mentioned isList.apply(n: Int): A
- Ruby equivalent
Array#[](range)
List.slice(from: Int, until: Int): List[A]
- no Ruby equivalent
Array#[](start, length)
There is also no Ruby equivalent Array#values_at
.
source to share