如何在Scala中按另一个列表拆分列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Scala中按另一个列表拆分列表相关的知识,希望对你有一定的参考价值。

我是Scala的新手,我需要解决我的问题。想象一下,我有这些列表:

val list1 = List(1,2,3,4,5,6,7,8,9,10,11)
val list2 = List(6,5)

我的愿望是使用list2分割列表列表中的第一个列表来映射它。所以结果将是这样的:

val result = List(List(1,2,3,4,5,6), List(7,8,9,10,11))

如果我的list2是这样的:

val list2 = List(4,4,3)

结果将是:

val result = List(List(1,2,3,4),List(5,6,7,8),List(9,10,11))

做这个的最好方式是什么?

答案

你可以使用scanLeftsplitAt的组合:

list2.scanLeft((List.empty[Int], list1)) { 
  case ((_, remaining), i) =>  remaining.splitAt(i)
}.unzip._1.tail

得到:

List(List(1, 2, 3, 4, 5, 6), List(7, 8, 9, 10, 11))

简要说明:scanLeft的每一步都将list1list1的其余元素保存在一个元组中。其余的元素根据下一个块的大小i进行拆分,其中ilist2的元素。最后,unzip._1抛弃了所有“剩余部分”,tail删除了第一个空虚元素。

请注意,由于列表结构是不可变的和持久的,因此在每个步骤中存储在元组的第二个组件中的中间结果不会占用任何额外的空间,它们仅仅是对list1尾部的引用。

另一答案

如果你正在做的是使用第二个列表作为第一个列表上的索引:

def indexedSplit[A](myList: List[A], indx: List[Int], acc: List[List[A]]): List[List[A]] = indx match{
  case Nil => acc.filter(_ != Nil).reverse
  case x :: xs => 
    val (h, t) = myList.splitAt(x)
    indexedSplit(t, xs, h :: acc)
}

其中您递归地遍历索引列表并在每个点的操作下拆分列表。最后,您过滤掉空列表并反转订单,因为您已按相反顺序累积。

另一答案
def foo[A](xs: List[A], ys: List[Int]): List[List[A]] = {
  val (result, _) = ys.foldLeft((List.empty[List[A]], xs)) { case ((acc, remaining), i) =>
    (remaining.take(i) :: acc, remaining.drop(i))
  }

  result.reverse
}

test("1") {
  val list1 = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
  val list2 = List(6, 5)
  val result = List(List(1, 2, 3, 4, 5, 6), List(7, 8, 9, 10, 11))

  foo(list1, list2) shouldBe result
}

test("2") {
  val list1 = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
  val list2 = List(4, 4, 3)
  val result = List(List(1, 2, 3, 4), List(5, 6, 7, 8), List(9, 10, 11))

  foo(list1, list2) shouldBe result
}

以上是关于如何在Scala中按另一个列表拆分列表的主要内容,如果未能解决你的问题,请参考以下文章

如何按另一个列表对列表进行排序

Scala附加列表

在每个谓词 scala 处将字符串列表拆分为多个列表

如何在模式匹配中拆分列表?

如何防止在android片段中按下后退按钮时调用onCreateView

将一个列表按另一个排序