如何根据指数从列表中返回多个项目?

时间:2015-06-16 21:32:17

标签: scala scala-collections

我们说,我有一个清单。如果我想在该列表的索引处返回一些内容,我可以通过列表' val,索引。像这样。

val list = List(1, 2, 3) 
list(0) //Int = 1

但是,如果我想在此列表中的多个索引处使用项目,该怎么办?我希望能够做到这一点...... list(0, 1)并获得这些指数的项目集合。

这在Ruby中非常简单。有人有什么建议吗?

3 个答案:

答案 0 :(得分:10)

您可以翻转逻辑,这样对于每个索引,您获得索引,就可以在该索引处检索元素。由于您在apply上使用List方法,因此该逻辑有几种简写表达式:

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

值得注意的是,由于这些都是maps indices,因此生成的集合通常与indices具有相同的类型,而不是list

val list = Array(1, 2, 3)
val indices = List(0, 1)
indices map list //List(1, 2), instead of Array(1, 2)

这可能是一个不受欢迎的财产。对此的一个解决方案是使用breakOut(在scala.collection中):

val newList: Array[Int] = indices.map(list)(breakOut)

您可以阅读有关breakOut here的更多信息。以下解决方案还可以通过list而不是list执行操作来维护indeces的集合类型:

如果您要查找列表的连续范围,可以考虑使用slice

list.slice(1, 2) //List(2)

您还可以使用droptake(以及dropRighttakeRight版本)来达到类似的效果:

list.drop(1).take(1)

对于此类过滤的更复杂版本,您可能对zipWithIndex方法感兴趣,该方法允许您在索引上表达任意逻辑:

list.zipWithIndex.collect { 
    case(el, index) if indices.contains(index) /* any other logic */ => el 
}

答案 1 :(得分:3)

@Ben的回答很明显。

但是,如果您希望能够使用您描述的语法list(0, 1),那么Scala允许您通过隐式转换执行此操作:

implicit class MultiIndexList[A](list: List[A]){
    def apply(indices: Int *) = indices.map(list)
}

假设您正在使用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)

答案 2 :(得分:1)

如果您正在寻找与Ruby的Array#slice(又名Array#[])方法相当的方法,那么有两种方法:

也没有相当于Ruby的Array#values_at