目前我有
val orders = new HashMap[Int, Int]
orders.put(36, 110)
orders.put(35, 90)
orders.put(34, 80)
orders.put(33, 60)
我想继续运行,以便结束映射如下所示
36 -> 110
35 -> 200
34 -> 280
33 -> 340
目前我必须按照以下方式执行此操作
val keys = orders.keys.toList.sortBy(x => -x)
val accum = new HashMap[Int, Int]
accum.put(keys.head, orders(keys.head))
for (i <- 1 to keys.length - 1) {
accum.put(keys(i), orders(keys(i)) + accum(keys(i-1)))
}
accum.foreach {
x => println(x._1, x._2)
}
使用映射,折叠等方法有更多功能吗?我可以用一个直接的列表来完成它但是我不能完全理解如何用HashMap做这个
编辑:订购非常重要。左列(36,35,34,33)需要按降序排列
答案 0 :(得分:6)
由于HashMaps没有排序,直接执行此操作并不是那么简单,因此首先转换为有序序列:
val elems = orders.toSeq.sortBy(-_._1)
.scanLeft(0,0)((x, y) => (y._1, x._2 + y._2)).tail
// ArrayBuffer((36,110), (35,200), (34,280), (33,340))
如果你真的想把它们放在一个反向排序的有序地图中,而不是只打印出来,你可以这样做:
val accum = collection.SortedMap(elems: _*)(
new Ordering[Int] { def compare(x: Int, y: Int) = y compare x })
// SortedMap[Int,Int] = Map(36 -> 110, 35 -> 200, 34 -> 280, 33 -> 340)
答案 1 :(得分:4)
这应该有效:
val orders = new HashMap[Int, Int]
orders.put(36, 110)
orders.put(35, 90)
orders.put(34, 80)
orders.put(33, 60)
val accum = new HashMap[Int, Int]
orders.toList.sortBy(-_._1).foldLeft(0){
case (sum, (k, v)) => {
accum.put(k, sum + v)
sum + v
}
}
答案 2 :(得分:3)
我认为你做错了。不要直接创建Map
:创建序列。在这种情况下,ListBuffer
可能是最合适的,因此您可以轻松地向其追加元素。它也支持恒定时间toList
,但这在这里无关紧要。
如果您必须使用功能方法,则可以预先添加到List
和reverse
,或者采用 iteratees 的方式。不过,我对后者的解释不够舒服。
收藏后,您将scanLeft
。或者,如果您构建了List
,则可以scanRight
而不是reverse
。之后,只需在结果上调用toMap
即可。
粗略地说:
var accum: List[(Int, Int)] = Nil
accum ::= 36 -> 110
accum ::= 35 -> 90
accum ::= 34 -> 80
accum ::= 33 -> 60
val orders = accum.scanRight(0 -> 0) {
case ((k, v), (_, acc)) => (k, v + acc)
}.init.toMap
init
掉落种子。我本可以避免使用tail
和head
来执行此操作,但这需要检查accum
是否为空。
可以使用iteratees删除var
,也可以使用更高级别的状态monad删除。{/ p>
答案 3 :(得分:3)
对于记录,这是使用inits
方法的解决方案:
import scala.collection.mutable._
// use a LinkedHashMap to keep the order
val orders = new LinkedHashMap[Int, Int]
orders.put(36, 110)
orders.put(35, 90)
orders.put(34, 80)
orders.put(33, 60)
// create a list of init sequences with no empty element
orders.toSeq.inits.toList.dropRight(1).
// > this returns
// ArrayBuffer((36,110), (35,90), (34,80), (33,60))
// ArrayBuffer((36,110), (35,90), (34,80))
// ArrayBuffer((36,110), (35,90))
// ArrayBuffer((36,110))
// now take the last key of each sequence and sum the values of the sequence
map(init => (init.last._1, init.map(_._2).sum)).reverse.toMap.mkString("\n")
36 -> 110
35 -> 200
34 -> 280
33 -> 340
答案 4 :(得分:0)
var sum = 0
orders.toList.sortBy (-_._1).map (o =>
{sum += o._2; (o._1 -> sum) }).toMap
不是很优雅,因为它使用了var。