我写了以下代码
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元素。
答案 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)