List scala对象列表,使用groupBy和average
基本上,我不是一个真正的Java/Scala爱好者,但不幸的是,我不得不在学习中使用它。不管怎样,我被分配了一个任务: 程序得到的是一个对象列表,如:List scala对象列表,使用groupBy和average,list,scala,group-by,List,Scala,Group By,基本上,我不是一个真正的Java/Scala爱好者,但不幸的是,我不得不在学习中使用它。不管怎样,我被分配了一个任务: 程序得到的是一个对象列表,如:Mark(val-name-String,val-style\u-Mark-Int,val-other\u-Mark-Int) 如何使用groupBy按名称对标记进行分组,并获得样式标记和其他标记的平均值 Mark("John", 2, 5) Mark("Peter", 3, 7) Mark("John", 4, 3) 应返回: Mark("Jo
Mark(val-name-String,val-style\u-Mark-Int,val-other\u-Mark-Int)
如何使用groupBy按名称对标记进行分组,并获得样式标记和其他标记的平均值
Mark("John", 2, 5)
Mark("Peter", 3, 7)
Mark("John", 4, 3)
应返回:
Mark("John", 3, 4)
Mark("Peter", 3, 7)
这就是代码:
class Mark(val name: String, val style_mark: Int, val other_mark: Int) {}
object Test extends Application
{
val m1 = new Mark("Smith", 18, 16);
val m2 = new Mark("Cole", 14, 7);
val m3 = new Mark("James", 13, 15);
val m4 = new Mark("Jones", 14, 16);
val m5 = new Mark("Richardson", 20, 19);
val m6 = new Mark("James", 4, 18);
val marks = List(m1, m2, m3, m4, m5, m6);
def avg(xs: List[Int]) = xs.sum / xs.length
marks.groupBy(_.name).map { kv => Mark(kv._1, avg(kv._2.map(_.style_mark)), avg(kv._2.map(_.other_mark))) }
println(marks);
}
任何帮助都将不胜感激
Paul正如您所说,我们可以使用
groupBy
按名称对标记进行分组。现在我们有了一个映射
,其中每个键都是名称,值是具有该名称的标记列表
现在,我们可以迭代该映射
,并用一个标记对象替换每个键值对,该标记对象的名称为键,列表中样式标记
s的平均值为其样式标记
,列表中其他标记
s的平均值为其其他标记
。像这样:
def avg(xs: List[Int]) = xs.sum / xs.length
marks.groupBy(_.name).map { kv =>
Mark(kv._1, avg(kv._2.map(_.style_mark)), avg(kv._2.map(_.other_mark)))
}
这里只有几点:
avg
替换为avgOf
,减少重复:)
在现实世界中,我可能希望pimp Traversable添加
avgOf
方法,这样您就可以编写v.avgOf(uu.styleMark)
,但这只会使这个示例变得复杂。谢谢您的回答,我有点明白了。用我知道的代码更新了我的问题,但它给了我一个错误错误:未找到:值标记在标记(kv._1,…
@Pawel:如果标记不是case类,你需要编写新标记(bla,bla,bla)
而不是标记(bla,bla,bla)
@Pawel:还要注意,标记的值将保持不变,因此您应该打印表达式的返回值,而不是标记的值(尽管在REPL中测试代码比创建文件并运行它更容易,在这种情况下,您只需输入表达式并查看其结果).在(k,v)
之前应该有案例
。这也不是我第一次犯这样的错误:)
//Needs two param lists so that inference will work properly
//when supplying the closure
def avgOf[T](xs:List[T])(f:(T)=>Int) = xs.map(f).sum / xs.length
marks.groupBy(_.name).map {
case (k,v) => new Mark(k, avgOf(v)(_.styleMark), avgOf(v)(_.otherMark))
}