映射减少字符串中的总和项目权重

map reduce sum item weights in a string

我有如下字符串:

s =  "eggs 103.24,eggs 345.22,milk 231.25,widgets 123.11,milk 14.2" 

这样一对item和它对应的weight用逗号隔开,item name和它的weight用space隔开。我想得到每个项目的重量总和:

//scala.collection.immutable.Map[String,Double] = Map(eggs -> 448.46, milk -> 245.45, widgets -> 123.11)

我已经完成了以下操作,但在分离物品及其重量的步骤上卡住了:

s.split(",").map(w=>(w,1)).sortWith(_._1 < _._1)

//Array[(String, Int)] = Array((eggs 345.22,1), (milk 14.2,1), (milk 231.25,1), (widgets 103.24,1), (widgets 123.11,1))

我想继续,对于数组中的每个元素,我需要分离出由 space 分隔的项目名称和权重,但是当我尝试以下操作时,我感到很困惑:

  s.split(",").map(w=>(w,1)).sortWith(_._1 < _._1).map(w => w._1.split(" ") )
  //Array[Array[String]] = Array(Array(eggs, 345.22), Array(milk, 14.2), Array(milk, 231.25), Array(widgets, 103.24), Array(widgets, 123.11))

我不确定下一步应该如何进行计算。

如果您保证字符串采用这种格式(因此没有异常和边缘情况处理),您可以这样做:

val s =  "eggs 103.24,eggs 345.22,milk 231.25,widgets 123.11,milk 14.2" 
val result = s
  .split(",") // array of strings like "eggs 103.24"
  .map(_.split(" ")) // sequence of arrays like ["egg", "103.24"]
  .map { case Array(x, y) => (x, y.toFloat)} // convert to tuples (key, number)
  .groupBy(_._1) // group by key
  .map(t => (t._1, t._2.map(_._2).sum)) // process groups, results in Map(eggs -> 448.46, ...)

与@GuruStron 提出的类似,但处理可能的错误(通过忽略任何类型的格式错误的数据)
此外,此版本需要 Scala 2.13+,旧版本将无法运行。

def mapReduce(data: String): Map[String, Double] =
  data
    .split(',')
    .iterator
    .map(_.split(' '))
    .collect {
      case Array(key, value) =>
        key.trim.toLowerCase -> value.toDoubleOption.getOrElse(default = 0)
    }.toList
    .groupMapReduce(_._1)(_._2)(_ + _)