Scala新手求助:如何使用另一个List拆分列表?
Scala列表拆分:用第二个List实现List of Lists
嘿,作为Scala新手碰到这种列表拆分需求太正常啦!我先结合你提到的“不同list2结构对应不同拆分结果”的情况,明确两种最常见的场景,再给出符合Scala函数式风格的最佳实现。
场景1:按list2指定的长度拆分源List
这种场景下,list2的每个元素代表要从源List中截取的子列表长度。比如:
- 源List:
val list1 = List(1, 2, 3, 4, 5, 6) - 长度指定List:
val list2 = List(2, 3, 1) - 期望结果:
List(List(1,2), List(3,4,5), List(6))
实现代码
我们可以用foldLeft来优雅地完成累加拆分,逻辑清晰且纯函数式:
def splitByLengths[A](source: List[A], lengths: List[Int]): List[List[A]] = { // 用foldLeft跟踪剩余元素和已拆分的结果 val (remainingElements, splitResult) = lengths.foldLeft((source, List.empty[List[A]])) { case ((remaining, result), currentLength) => val (currentChunk, newRemaining) = remaining.splitAt(currentLength) (newRemaining, result :+ currentChunk) } // 如果源List还有剩余元素,把它加到结果末尾(可选,根据你的需求调整) if (remainingElements.nonEmpty) splitResult :+ remainingElements else splitResult } // 测试一下 val list1 = List(1,2,3,4,5,6) val list2 = List(2,3,1) println(splitByLengths(list1, list2)) // 输出: List(List(1, 2), List(3, 4, 5), List(6))
代码说明
foldLeft初始状态是**(源List, 空结果列表)**,每次迭代按当前长度截取子列表,更新剩余元素和结果列表- 最后判断是否有剩余元素,可选追加到结果中,适配长度总和小于源List长度的情况
场景2:按list2中的元素作为分隔符拆分源List
这种场景下,list2的元素是拆分的分隔点,源List会被这些分隔符切成多个子列表。比如:
- 源List:
val list1 = List(1, 2, 0, 3, 4, 5, 0, 6) - 分隔符List:
val list2 = List(0) - 期望结果:
List(List(1,2), List(3,4,5), List(6))
实现代码
用递归+span方法可以简洁处理,符合Scala的函数式思维:
def splitByDelimiters[A](source: List[A], delimiters: List[A]): List[List[A]] = { source match { // 源List为空时直接返回空 case Nil => Nil case _ => // 取到第一个分隔符之前的所有元素作为当前子列表 val (currentChunk, rest) = source.span(element => !delimiters.contains(element)) // 跳过所有连续的分隔符,递归处理剩余部分 currentChunk :: splitByDelimiters(rest.dropWhile(delimiters.contains(_)), delimiters) } } // 测试示例1 val list1 = List(1,2,0,3,4,5,0,6) val list2 = List(0) println(splitByDelimiters(list1, list2)) // 输出: List(List(1, 2), List(3, 4, 5), List(6)) // 测试多分隔符场景 val list3 = List(1,2,0,3,4,5,4,6) val list4 = List(0,4) println(splitByDelimiters(list3, list4)) // 输出: List(List(1, 2), List(3), List(5), List(6))
代码说明
- 递归遍历源List,每次用
span截取到第一个分隔符前的元素 dropWhile跳过所有连续的分隔符,避免结果中出现空列表- 纯递归实现,没有可变状态,符合Scala的最佳实践
总结
具体用哪种实现完全取决于你的实际需求:如果是按长度拆分就用第一种,按分隔符拆分就用第二种。这两种实现都是纯函数式的,可读性高且易于扩展。
内容的提问来源于stack exchange,提问作者André Azevedo
相关产品推荐
相关产品推荐

