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

use*_*418 3 scala scala-collections

比方说,我有一个清单.如果我想在该列表的索引处返回一些内容,我可以传递列表'val,索引.像这样.

val list = List(1, 2, 3) 
list(0) //Int = 1
Run Code Online (Sandbox Code Playgroud)

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

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

Ben*_*ich 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
Run Code Online (Sandbox Code Playgroud)

值得注意的是,由于这些都是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)
Run Code Online (Sandbox Code Playgroud)

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

val newList: Array[Int] = indices.map(list)(breakOut)
Run Code Online (Sandbox Code Playgroud)

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

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

list.slice(1, 2) //List(2)
Run Code Online (Sandbox Code Playgroud)

您也可以使用droptake(与dropRight,takeRight版本)到类似的效果:

list.drop(1).take(1)
Run Code Online (Sandbox Code Playgroud)

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

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

  • 你甚至不需要括号或圆点.`indeces map list``会做到这一点. (4认同)
  • 由于泛型变量名称,`indeces.map(list)`可能看起来模糊不清.一旦习惯了函数式编程,`positions.map(itemByPosition)`就像它可读的一样. (2认同)

mar*_*ios 5

@Ben 的回答很准确。

但是,如果您希望能够使用您所描述的语法list(0, 1),那么 Scala 允许您通过隐式转换来实现这一点:

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

假设您正在开发 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)
Run Code Online (Sandbox Code Playgroud)

  • 我同意。这有点高级了。我只是想证明 Scala 比 Ruby 更酷:)。 (4认同)
  • 这是一项需要掌握的重要技术,在类似情况下绝对是一个不错的选择,但对于这样一个简单而常见的问题,我会鼓励 OP 使用该语言公认的习惯用法 (3认同)