如何在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))
做这个的最好方式是什么?
答案
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
的每一步都将list1
和list1
的其余元素保存在一个元组中。其余的元素根据下一个块的大小i
进行拆分,其中i
是list2
的元素。最后,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中按另一个列表拆分列表的主要内容,如果未能解决你的问题,请参考以下文章