按索引筛选列表

时间:2015-10-03 18:17:56

标签: scala functional-programming

如何按存储在另一个列表中的索引过滤列表? 例如,我有以下值列表:

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

和索引列表:

val indexes = List(1,2,5)

我想获得以下列表:

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

最惯用的方式是什么?

5 个答案:

答案 0 :(得分:6)

为避免创建过多的中间对象,您可以编写

indexes.map(list.lift).flatten

使用索引序列,列表中的查找时间将保持不变。这既是惯用又有效的。如果list的类型为List,其查找时间为O(n),那么你有O(m * n),其中m是索引的长度,n是列表的长度。

这与indexes.map(list)之间的区别在于,如果在列表中找不到索引,是否要抛出异常。

list.lift创建一个带索引的函数,如果存在则返回Some(value),否则返回None。 flatten方法展平了生成的选项列表。它会删除所有无结果,并从Some results中提取值。

答案 1 :(得分:5)

你可以这样做:

indexes.map(list)

的缩写
indexes.map(index => list.apply(index))

尽管如此,我建议使用针对索引优化的内容(IndexedSeq)。

答案 2 :(得分:3)

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

答案 3 :(得分:2)

使用zipWithIndex将索引添加到第一个列表中:

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

可能更好地将允许的索引表示为Set:

val indexes = Set(1, 2, 5)

然后根据Set的成员资格进行过滤,并映射回原始字符串:

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

答案 4 :(得分:0)

使用for comprehension如下,

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

使用foldLeft如下,

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