我们说,我有一个清单。如果我想在该列表的索引处返回一些内容,我可以通过列表' val,索引。像这样。
val list = List(1, 2, 3)
list(0) //Int = 1
但是,如果我想在此列表中的多个索引处使用项目,该怎么办?我希望能够做到这一点...... list(0, 1)
并获得这些指数的项目集合。
这在Ruby中非常简单。有人有什么建议吗?
答案 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)
您还可以使用drop
和take
(以及dropRight
,takeRight
版本)来达到类似的效果:
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#[]
)方法相当的方法,那么有两种方法:
Array#[](index)
,正如您所提到的,List.apply(n: Int): A
Array#[](range)
是List.slice(from: Int, until: Int): List[A]
Array#[](start, length)
也没有相当于Ruby的Array#values_at
。