How to split a list by another list in Scala

后端 未结 3 1558
清酒与你
清酒与你 2021-01-16 06:10

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)

相关标签:
3条回答
  • 2021-01-16 06:40

    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.

    0 讨论(0)
  • 2021-01-16 06:41

    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.

    0 讨论(0)
  • 2021-01-16 06:47
    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
    }
    
    0 讨论(0)
提交回复
热议问题