【问题标题】:How to return multiple items from a list, given their indices?给定索引,如何从列表中返回多个项目?
【发布时间】:2016-07-13 01:30:51
【问题描述】:

假设,我有一个清单。如果我想在该列表的索引处返回某些内容,我可以传递列表的 val,即索引。像这样。

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

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

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

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    您可以翻转逻辑,以便为每个索引获取索引,然后检索该索引处的元素。由于您在List 上使用了apply 方法,因此该逻辑有几个速记表达式:

    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 on 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 而不是indeces 执行操作,尽可能保持list 的集合类型:

    如果您正在寻找列表的连续范围,您可以考虑使用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 
    }
    

    【讨论】:

    • 我认为 OP 想要一个简单而优雅的解决方案,与 Ruby 相媲美。
    • 对我来说它很优雅。 +1
    • 我猜美丽在情人眼里;对我来说这很丑。
    • 你甚至不需要括号或点。 indeces map list`会做的。
    • indeces.map(list) 可能会因为通用变量名称而被混淆。一旦你习惯了函数式编程,positions.map(itemByPosition) 就会变得可读性极强。
    【解决方案2】:

    @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)
    

    【讨论】:

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

    如果您正在寻找与 Ruby 的 Array#slice(又名 Array#[])方法等效的方法,则有两种:

    也没有与 Ruby 的 Array#values_at 等效的东西。

    【讨论】:

    • 猜测Array#[](start, length) 做了什么seq.drop(start).take(length) 可能会做到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 2015-05-15
    • 2014-09-20
    • 1970-01-01
    • 2018-07-02
    • 2015-09-20
    相关资源
    最近更新 更多