【问题标题】:Splitting a Scala List into parts using a given list of part sizes.[Partitioning]使用给定的部件尺寸列表将 Scala 列表拆分为多个部件。[分区]
【发布时间】:2018-12-22 10:25:41
【问题描述】:

我有两个列表:

val list1:List[Int]   =  List(5, 2, 6)

val list2:List[Any]  =  List("a", "b", "c", "d", "e", "f", "g", "h", "i", "j","k")

这样list1.sum >= list2.size

我想要一个由 list2 中的元素连续组成的列表列表 使用 list1 中提到的尺寸。

例如:

如果 list1 是 List(5,2,4) 我想要的结果是:

List(List("a", "b", "c", "d", "e"),List("f", "g"),List("h", "i", "j","k"))

如果 list1 是 List(5,4,6) 我想要的结果是:

List(List("a", "b", "c", "d", "e"),List("f", "g","h", "i"),List("j","k"))

如何用简洁的代码做到这一点。

【问题讨论】:

    标签: scala list collections


    【解决方案1】:

    list2 转换为Iterator,然后映射到list1

    val itr = list2.iterator
    list1.map(itr.take(_).toList)
    //res0: List[List[Any]] = List(List(a, b, c, d, e), List(f, g), List(h, i, j, k))
    

    更新: 虽然这似乎给出了预期的结果,但在其他地方已经指出,重用迭代器实际上是不安全的,并且它的行为没有得到保证。

    通过一些修改可以获得更安全的版本。

    val itr = list2.iterator
    list1.map(List.fill(_)(if (itr.hasNext) Some(itr.next) else None).flatten)
    

    -- 或--

    import util.Try
    val itr = list2.iterator
    list1.map(List.fill(_)(Try(itr.next).toOption).flatten)
    

    【讨论】:

    【解决方案2】:

    您可以根据从list1 获得的大小对list2 进行切片,

      def main(args: Array[String]): Unit = {
    
        val groupingList: List[Int] = List(5, 2, 4)
        val data = List("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k")
    
        //0, 5
        //5, (5 + 2)
        //5 + 2, (5 + 2 + 4)
    
        val grouped = groupingList.zipWithIndex.map { case (_, index) =>
          val start = groupingList.slice(0, index).sum
          val end = groupingList.slice(0, index + 1).sum
    
          data.slice(start, end)
        }
    
        println(grouped)
      }
    

    结果: List(List(a, b, c, d, e), List(f, g), List(h, i, j, k))

    另请阅读:How slice works

    【讨论】:

      【解决方案3】:

      我喜欢用 ex 来展示它 list1=List("一","二","三") List[String] = List(一、二、三)

      list2=列表("红色","绿色","蓝色") List[String] = List(红、绿、蓝)

      list1::list2 List[java.io.Serializable] = List(List(一、二、三)、红、绿、蓝)

      var listSum=list1::list2 List[java.io.Serializable] = List(List(一、二、三)、红、绿、蓝)

      列表总和 List[java.io.Serializable] = List(List(一、二、三)、红、绿、蓝)

      我们可以用“::”将一个列表插入到Scala中的另一个列表中

      【讨论】:

        【解决方案4】:

        我刚刚发现,即使以下代码也有效,但 jwvh 发布的代码似乎比这更简洁,我理解将 list1 设为 Vector 对以下代码中元素访问的性能更有意义:

        list1.scan(0)(_+_).sliding(2).toList.map(x=>list2.drop(x(0)).take(x(1)-x(0)))
        

        list1.scan(0)(_+_).zip(list1).map(x=>list2.drop(x._1).take(x._2))
        
        list1.scan(0)(_+_).sliding(2).map(x=>list2.slice(x(0),x(1))).toList
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-09
          • 1970-01-01
          相关资源
          最近更新 更多