Scala列出了处理

时间:2018-05-13 21:17:41

标签: scala

我写了以下代码

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元素。

2 个答案:

答案 0 :(得分: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生成的键值对,标签(" apple"等)是键,数组列表是值。
  • 模式匹配case (label, listOfArrays) => ...用于提取键和值
  • listOfArrays.map(_(i).toInt).sum从每个数组中提取i个组件,然后计算这些组件的总和。
  • 使用String.format模式"%s %d %d %s"将标签和总和再次合并为一个字符串,代表"字符串十进制十进制字符串"。

代码中最常见的错误:

  • i - 数组a的元素访问为a(i),无需明确写出a.apply(i)
  • i - _i
  • 访问访问数组的元素
  • groupBy之后,您获得了一张地图。映射本质上是键值对的集合。键值对包含元素_1_2,但不包含_3
  • 如果每个条目都匹配,则不需要
  • collect。请改用map(这与我前几天here指出的问题完全相同)。

答案 1 :(得分:0)

我更希望使用case 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)