Nyavro
Nyavro

Reputation: 8866

Filter list by indexes

How do I filter list by indexes stored in another list? For instance I have the following list of values:

val list = List("a", "b", "c", "d", "e", "f")

and the list of indexes:

val indexes = List(1,2,5)

I want to get the following list:

List("b", "c", "f)

What is the most idiomatic way?

Upvotes: 2

Views: 2531

Answers (5)

elm
elm

Reputation: 20435

Using a for comprehension as follows,

for ( (v,i) <- list.zipWithIndex if indexes.contains(i) ) yield v

Using foldLeft as follows,

indexes.foldLeft(List[String]())( (xs,i) => xs :+ list(i) )

Upvotes: 0

1gLassitude
1gLassitude

Reputation: 81

To avoid creating too many intermediary objects, you could write

indexes.map(list.lift).flatten

With an indexed sequence, lookup time in the list would be constant. It's both idiomatic and efficient. If list is of type List, which has lookup time is O(n), then the you have O(m * n), where m is the length of indexes, and n is the length of the list.

The difference between this and indexes.map(list) is whether or not you want to throw an exception if an index is not found in the list.

list.lift creates a function that takes an index and returns Some(value) if it exists, and None otherwise. The flatten method flattens the resulting List of Option. It removes all the None results, and extracts the values from the Some results.

Upvotes: 6

Sascha Kolberg
Sascha Kolberg

Reputation: 7162

You can do just:

indexes.map(list)

which is short for

indexes.map(index => list.apply(index))

Though, I would recommend to use something that is optimized for indexes (IndexedSeq).

Upvotes: 5

mattinbits
mattinbits

Reputation: 10428

Use zipWithIndex to add the indexes to the first list:

val l = List("a", "b", "c", "d", "e", "f").zipWithIndex

Probably better to represent the allowed indexes as a Set:

val indexes = Set(1, 2, 5)

Then simply filter based on membership of the Set and map back to the original Strings:

l.filter(tuple => indexes.contains(tuple._2)).map(_._1)

Upvotes: 2

Łukasz
Łukasz

Reputation: 8673

list.zipWithIndex.filter(indexes contains _._2).map(_._1)

Upvotes: 3

Related Questions