Scala技术求助:合并同标题行的对应整数值并求和
Scala: Sum integer values for rows with matching title-type pairs in a string list
Problem Statement
I have a list of comma-separated strings where each entry follows the format [Title],[Type],[IntValue1],[IntValue2]. My goal is to merge rows that share the same [Title],[Type] pair by summing their corresponding integer values.
Input List
val listIn = List("TitleB,Int,11,0", "TitleB,Int,1,0", "TitleB,Int,1,0", "TitleB,Int,3,0", "TitleA,STR,3,0", "TitleC,STR,4,5")
Expected Output
List("TitleB,Int,16,0", "TitleA,STR,3,0", "TitleC,STR,4,5")
My Current Code
def sumB(list: List[String]): List[String] = { val itemPattern = raw".*(\d+),(\d+)\s*".r list.foldLeft(ListMap.empty[String, (Int,Int)].withDefaultValue((0,0))) { case (line, stri) => val itemPattern(k,i,j) = stri val (a, b) = line(k) line.updated(k, (i.toInt + a, j.toInt + b)) }.toList.map { case (k, (i, j)) => s"$k$i,$j" } }
Issues with the Current Code
Let's break down what's not working here:
- Incorrect Regex Pattern: The regex
.*(\d+),(\d+)\s*only captures the last two integer values, but it doesn't extract the[Title],[Type]pair we need as the grouping key. Worse, you're trying to assign three groups (k,i,j) to a regex that only has two capture groups—this will throw a match error. - Wrong Grouping Key: Even if the regex worked, you aren't capturing the actual unique identifier (the first two comma-separated fields) that should group rows together.
- Malformed Output String: The final interpolation
s"$k$i,$j"is missing a comma between the key and the first summed integer, leading to broken output likeTitleBInt16,0instead of the desired format.
Fixed Solution
Here's a revised version that addresses all these issues:
import scala.collection.immutable.ListMap def sumB(list: List[String]): List[String] = { // Split each string by commas to extract components safely list.foldLeft(ListMap.empty[String, (Int, Int)].withDefaultValue((0, 0))) { case (acc, line) => line.split(",") match { case Array(title, typ, num1, num2) => // Use title+typ as the unique key (joined with comma to match input format) val key = s"$title,$typ" val (sum1, sum2) = acc(key) acc.updated(key, (sum1 + num1.toInt, sum2 + num2.toInt)) // Handle invalid lines gracefully (optional but robust) case _ => acc } }.map { case (key, (sum1, sum2)) => // Reconstruct the output string with proper formatting s"$key,$sum1,$sum2" }.toList }
Explanation
- Safe Splitting: Instead of brittle regex, we use
split(",")to directly pull out each component of the string. This makes it trivial to get the title/type pair for grouping and the integers to sum. - Correct Grouping: We create the key as
s"$title,$typ"to ensure we only merge rows that have both the same title and type (which aligns with your expected output, keeping TitleA/STR and TitleC/STR separate). - Proper Formatting: The final string interpolation correctly combines the key with summed values using commas, producing exactly the format you need.
- Robustness: The
case _ => accclause ensures malformed input lines don't break the function—they're just skipped.
Testing the Solution
Run it with your input list:
sumB(listIn)
You'll get the exact expected output:
List("TitleB,Int,16,0", "TitleA,STR,3,0", "TitleC,STR,4,5")
内容的提问来源于stack exchange,提问作者scalacode
相关产品推荐
相关产品推荐

