0

我写了以下代码

val listInput=List("banana  10 10 rr", 
  "apple   20  10 rr",
  "apple   30  10 rr",
  "banana   10 10 rr",
  "berry    10  10 rr")

val result = listInput.map(_.split("\\s+")).groupBy(e=> e.apply(0)).collect{
  case e=> (e._1, e._2.map(_.apply(1).toInt).sum, e._2.map(_.apply(2).toInt).sum,e._2.map(._3)}

我收到一个错误实际上,想要的结果应该是:

val listoutput=List("banana  20 20 rr",    
  "apple   50  20 rr",      
  "berry    10  10 rr")

我的问题是我无法访问每行的 rr 元素。

4

2 回答 2

0

这里:

val listInput = List(
  "banana  10 10 rr",
  "apple   20  10 rr",
  "apple   30  10 rr",
  "banana   10 10 rr",
  "berry    10  10 rr"
)

val result = listInput
  .map(_.split("\\s+"))
  .groupBy(_(0))
  .map{ case (label, listOfArrays) => 
     "%s %d %d %s".format(
       label,
       listOfArrays.map(_(1).toInt).sum,
       listOfArrays.map(_(2).toInt).sum,
       listOfArrays.head.apply(3)
     )
  }

println(result)

产生:

List(banana 20 20 rr, apple 50 20 rr, berry 10 10 rr)

解释:

  • _.split(...)将字符串转换为子字符串数组
  • groupBy(_(0))按第一个子字符串(标签“apple”等)对数组进行分组
  • map生成的键值对的作品groupBy,标签(“苹果”等)是键,数组列表是值。
  • 模式匹配case (label, listOfArrays) => ...用于提取键和值
  • listOfArrays.map(_(i).toInt).sum从每个数组中提取i-th 分量,然后计算这些分量的总和。
  • 标签和总和再次使用String.formatwith pattern组合成一个字符串"%s %d %d %s",它代表“字符串十进制十进制字符串”。

代码中最常见的错误:

  • i- 数组的第一个元素a被访问为a(i),不需要a.apply(i)显式写出
  • i- 数组的第一个元素未被访问_i
  • 之后groupBy,您将获得一张地图。映射本质上是键值对的集合。键值对包含元素_1and _2,但不包含_3
  • collect如果每个条目都匹配,则不需要。改为使用(这与我几天前在这里map指出的完全相同的问题)。
于 2018-05-13T21:31:23.353 回答
0

我希望 acase class使可读性更好一些。并且scalaz还提供了|+|直接添加元组的功能。这是示例代码。

import scalaz._
import Scalaz._
val listInput=List("banana 10 10 rr",
  "apple   20  10 rr",
  "apple   30  10 rr",
  "banana   10 10 rr",
  "berry    10  10 rr")


case class Foo(name:String, value1:Int, value2:Int, tag:String){
  override def toString = s"${name} ${value1} ${value2} ${tag}"
}
listInput
.map(_.split("\\s+").toList)
.map{
  case a::b::c::d::Nil =>
  Foo(a, b.toInt, c.toInt, d)
}
.groupBy(x => (x.name, x.tag))
.map{
  case ((n, t), y) =>
  val (v1, v2) = y.map(s => (s.value1, s.value2)).reduce(_|+|_)
  Foo(name = n, tag = t, value1 = v1, value2 = v2)
}.map(_.toString)
于 2018-05-14T03:22:27.807 回答