groupby scala字符串列表
在计算Scala中具有相同标题(本例中为我的键)的元素之和时,我面临一个问题 目前,我的输入可以描述为:groupby scala字符串列表,scala,group-by,Scala,Group By,在计算Scala中具有相同标题(本例中为我的键)的元素之和时,我面临一个问题 目前,我的输入可以描述为: val listInput1 = List( "itemA,CATA,2,4 ", "itemA,CATA,3,1 ", "itemB,CATB,4,5", "itemB,CATB,4,6" ) val listInput2 = List( "itemA,CATA,2,4 ", "itemB,CATB,4,5", "
val listInput1 =
List(
"itemA,CATA,2,4 ",
"itemA,CATA,3,1 ",
"itemB,CATB,4,5",
"itemB,CATB,4,6"
)
val listInput2 =
List(
"itemA,CATA,2,4 ",
"itemB,CATB,4,5",
"itemC,CATC,1,2"
)
输入中列表所需的输出应为
val listoutput1 =
List(
"itemA,CATA,5,5 ",
"itemB,CATB,8,11"
)
val listoutput2 =
List(
"itemA , CATA, 2,4 ",
"itemB,CATB,4,5",
"itemC,CATC,1,2"
)
我编写了以下函数:
def sumByTitle(listInput: List[String]): List[String] =
listInput.map(_.split(",")).groupBy(_(0)).map {
case (title, features) =>
"%s,%s,%d,%d".format(
title,
features.head.apply(1),
features.map(_(2).toInt).sum,
features.map(_(3).toInt).sum)}.toList
它没有给我预期的结果,因为它改变了行的顺序
如何解决此问题?如果您对排序感兴趣,只需返回
排序的列表:
val listInput1 =
List(
"itemA , CATA, 2,4 ",
"itemA , CATA, 3,1 ",
"itemB,CATB,4,5",
"itemB,CATB,4,6"
)
val listInput2 =
List(
"itemA , CATA, 2,4 ",
"itemB,CATB,4,5",
"itemC,CATC,1,2"
)
def sumByTitle(listInput: List[String]): List[String] =
listInput.map(_.split(",")).groupBy(_(0)).map {
case (title, features) =>
"%s,%s,%d,%d".format(
title,
features.head.apply(1),
features.map(_(2).trim.toInt).sum,
features.map(_(3).trim.toInt).sum)}.toList.sorted
println("LIST 1")
sumByTitle(listInput1).foreach(println)
println("LIST 2")
sumByTitle(listInput2).foreach(println)
您可以找到代码供您使用
作为补充说明,您可能对从业务逻辑中分离序列化和反序列化感兴趣
以一种相对幼稚的方法,迈出了分离关注点的第一步
def foldByTitle(listInput: List[String]): List[Item] =
listInput.map(Item.parseItem).foldLeft(List.empty[Item])(sumByTitle)
val sumByTitle: (List[Item], Item) => List[Item] = (acc, curr) =>
acc.find(_.name == curr.name).fold(curr :: acc) { i =>
acc.filterNot(_.name == curr.name) :+ i.copy(num1 = i.num1 + curr.num1, num2 = i.num2 + curr.num2)
}
case class Item(name: String, category: String, num1: Int, num2: Int)
object Item {
def parseItem(serializedItem: String): Item = {
val itemTokens = serializedItem.split(",").map(_.trim)
Item(itemTokens.head, itemTokens(1), itemTokens(2).toInt, itemTokens(3).toInt)
}
}
这样可以保留元素的初始顺序。列表映射
旨在保留插入到映射
的项目顺序
import collection.immutable.ListMap
def sumByTitle(listInput: List[String]): List[String] = {
val itemPttrn = raw"(.*)(\d+),(\d+)\s*".r
listInput.foldLeft(ListMap.empty[String, (Int,Int)].withDefaultValue((0,0))) {
case (lm, str) =>
val itemPttrn(k, a, b) = str //unsafe
val (x, y) = lm(k)
lm.updated(k, (a.toInt + x, b.toInt + y))
}.toList.map { case (k, (a, b)) => s"$k$a,$b" }
}
这有点不安全,因为如果输入字符串与正则表达式模式不匹配,它将抛出
sumByTitle(listInput1)
//res0: List[String] = List(itemA,CATA,5,5, itemB,CATB,8,11)
sumByTitle(listInput2)
//res1: List[String] = List(itemA,CATA,2,4, itemB,CATB,4,5, itemC,CATC,1,2)
您会注意到尾随空格(如果有)没有保留。我的目的不是排序,我只想保持与输入中列表相同的顺序。据我所知,累积结果的顺序应该与原始列表中元素的顺序相似。这并不意味着原始列表中的元素是按字母顺序排序的。我是否有可能只用一个函数就可以做到这一点,这里不需要case cals hello所需输出中的所有空格都是错误的。我纠正了它。请你换一下房间好吗code@scalacode; 不需要更改代码。输入格式保留在输出中,除了任何尾随空格。这是否保证在列表中,我们将始终按排序顺序获得输入,如第一组A然后B?