Scala匹配错误案例预防:多子列表match匹配失败问题
Hey there! Let's figure out how to fix this pattern matching issue and make your function handle any number of sublists smoothly.
First, let's break down the problem with your current code: your pattern matching only covers two cases—when the input has 1 sublist (head :: Nil) and 2 sublists (head :: tail :: Nil). When you pass an input with 3 or more sublists, there's no matching branch, which triggers a MatchError.
The solution here is to use recursion instead of hardcoding branches for every possible length. This way, we can build up combinations incrementally, reusing the same logic for combining two sets of results each time.
Refactored Recursive Solution
Here's how to rewrite your function to support any number of sublists, while preserving your original element non-overlapping constraint:
def combinationList[T](ls: List[List[List[T]]]): List[List[List[T]]] = ls match { // Handle empty input case to avoid unexpected errors case Nil => Nil // Single sublist: wrap each element in a nested list (matches your original logic) case head :: Nil => head.map(List(_)) // Multiple sublists: recurse on the tail, then combine with the head case head :: tail => // First get all valid combinations from the remaining sublists val tailCombinations = combinationList(tail) // Combine each element from the head with each valid tail combination for { sublist <- head combo <- tailCombinations // Ensure the new sublist has no overlapping elements with any in the existing combo if combo.flatten.forall(element => !sublist.contains(element)) } yield sublist :: combo }
How This Works
Base Cases:
- If the input is empty (
Nil), return an empty list (clean edge case handling). - If there's only one sublist, we wrap each element in a nested list (exactly what your original code does).
- If the input is empty (
Recursive Case:
- We first recursively compute all valid combinations for the tail (all sublists except the first one).
- Then, we iterate over every element in the first sublist, and every valid combination from the tail. For each pair, we check if the new sublist has no overlapping elements with any sublist in the existing combination (preserving your original constraint).
- Valid pairs are combined into a new nested list, building up combinations of arbitrary length.
Example Tests
Let's verify this works with different input sizes:
1. Single Sublist Input
val singleInput = List(List(List(1,2), List(3,4))) combinationList(singleInput) // Output: List(List(List(1,2)), List(List(3,4)))
2. Two Sublists Input
val twoInput = List(List(List(1,2), List(5)), List(List(3,4), List(6))) combinationList(twoInput) // Output: List( // List(List(1,2), List(3,4)), // List(List(1,2), List(6)), // List(List(5), List(3,4)), // List(List(5), List(6)) // )
3. Three Sublists Input
val threeInput = List(List(List(1)), List(List(2)), List(List(3))) combinationList(threeInput) // Output: List(List(List(1), List(2), List(3)))
This approach scales seamlessly to any number of sublists without needing to add more pattern matching branches.
内容的提问来源于stack exchange,提问作者Pedro Gonçalves

