How to split a list by another list in Scala

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I am new to Scala and I need a solution to my problem. Imagine I have these lists:

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

And my desire is to split the first list in a List of Lists using list2 to map it. So the result would be something like this:

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

If my list2 was like this:

val list2 = List(4,4,3) 

The result would then be:

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

What is the best way to do this?

回答1:

You can use a combination of scanLeft and splitAt:

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

Gives:

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

Brief explanation: each step of scanLeft saves each piece of list1 and the remaining elements of list1 in a tuple. The remaining elements are split according to the size i of next chunk, where i is an element of list2. In the end, all the "remainders" are thrown away by unzip._1, and the first empty dummy-element is removed by tail.

Note that since the list structure is immutable & persistent, the intermediate results stored in the second component of the tuple in each step do not take up any extra space, they are mere references to tails of list1.



回答2:

If what you're doing is using the second list to be the indexes on the first list:

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

wherein you recursively walk the index list and split the list under operation at each of those points. Finally you filter out empty lists and reverse the order since you've accumulated in reverse order.



回答3:

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 } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!