如果我有一个对象列表(所有相同类型),我可以从中获得某种类型的地图,其中地图中的每个条目对应于该类型的成员(无论这是由我设置还是由system是无关紧要的)并且每个条目的值是列表中所有成员值的总和?
例如,给定一个具有成员薪水,小时和身高的对象,以及其中几个对象的列表,是否有一些scala代码可以让我回到一个带有" height"作为高峰的总和,"薪水"作为工资和"小时"的总和作为小时数的总和?
抱歉,我对Scala完全不熟悉 - 我只是想尝试使用Twirl在playframework中工作。
答案 0 :(得分:1)
这是一种方法。
我们将创建一个案例类Item来表示具有高度,小时和工资成员的类,以及它们的列表:
case class Item(val height: Int, val hours: Int, val salary: Double)
val items = List(Item(3, 4, 10.0), Item(9, 100, 123.0))
然后只需初始化一个3元组并使用foldLeft来累积每个成员的总和。
val sums = items.foldLeft((0, 0, 0.0))((x, item) =>
(x._1 + item.height, x._2 + item.hours, x._3 + item.salary))
我们可以将值累积到Item的另一个实例中,或者累积到具有三个成员的Map中。这没关系。原理是相同的:初始化一个对象以保存总和,然后foldLeft在集合上。
使用元组(而不是您请求的映射)的好处是您可以将每个元组成员分配给一个单独的变量:
val (sumHeight, sumHurs, sumSalary) = items.foldLeft((0, 0, 0.0))((x, item) =>
(x._1 + item.height, x._2 + item.hours, x._3 + item.salary))
答案 1 :(得分:0)
我的解决方案略有不同。 如果您只想对所有项目求和,Scala集合已经提供了一个'sum'函数来汇总项目。 但是,为了能够使用它,您需要为案例类使用Numeric实现。
因此对于案例类Item:
case class Item(salary: Double, hours: Int, height: Int)
可以在Item的伴随对象中定义隐式Numeric [Item]实例:
object Item {
implicit object NumericItem extends Numeric[Item] {
override def plus(x: Item, y: Item): Item = Item(
salary = x.salary + y.salary,
hours = x.hours + y.hours,
height = x.height + y.height
)
override def minus(x: Item, y: Item): Item = ???
override def times(x: Item, y: Item): Item = ???
override def negate(x: Item): Item = ???
// Needed to provide starting point for folding using 'sum'
override def fromInt(x: Int): Item = {
Item(0,0,0)
}
override def toInt(x: Item): Int = ???
override def toLong(x: Item): Long = ???
override def toFloat(x: Item): Float = ???
override def toDouble(x: Item): Double = ???
override def compare(x: Item, y: Item): Int = ???
}
}
为了支持'sum'功能,只需要实现Numeric的'plus'和'fromInt'功能。
现在列表中的所有项目
val items = List(Item(10.0, 1, 5), Item(5.0, 2, 3), Item(2.5, 3, 8))
items: List[Item] = List(Item(10.0,1,5), Item(5.0,2,3), Item(2.5,3,8))
可以使用'sum'
求和val total = items.sum
total: Item = Item(17.5,6,16)
现在总数可以用作'total.salary'等,但是如果你想要一张地图,可以在Item中提供一个简单的'toMap'功能
def toMap: Map[String, Any] = Map(
"salary" -> salary,
"hours" -> hours,
"height" -> height
)
总计地图可以通过
获得totals.toMap
res0: Map[String,Any] = Map(salary -> 17.5, hours -> 6, height -> 16)