我有一个包含Salesman,Product,Location,SalesValue
数据的文件例如:
Bob, Carrots, United States, 200
Bill, Potatoes, England, 100
Bob, Oranges, England, 50
Bob, Carrots, United States, 20
可以使用以下代码将SalesValue简洁地累积到perl中哈希的哈希值
while(<>){
@cols = split(/,/);
$vals {$cols[0]} {$cols[1]} {$cols[2]} += $cols[3];
}
有没有人有任何建议如何创建地图地图的地图,加上积累,最好能在scala中实现?
答案 0 :(得分:6)
我建议将这些地图合并为monoid-append
操作。
首先,我们将地图地图的地图创建为单个元素:
val input = """Bob, Carrots, United States, 200
|Bill, Potatoes, England, 100
|Bob, Oranges, England, 50
|Bob, Carrots, United States, 20""".stripMargin.lines.toList
val mmm = input.map(_.split(", "))
.map { case Array(n, g, c, v) => Map(n -> Map(g -> Map(c -> v.toInt))) }
mmm
的类型为List[Map[String, Map[String, Map[String, Int]]]]
:
List[Map[String,
Map[String,
Map[String, Int]]]]
然后我们可以suml
使用scalaz
或cats
这样的库:
import scalaz._, Scalaz._
println(mmm.suml)
这将打印(未提交):
Map(Bill -> Map(Potatoes -> Map(England -> 100)),
Bob -> Map(Oranges -> Map(England -> 50),
Carrots -> Map(United States -> 220)))
为了帮助了解.suml
操作背后发生的情况,我会无耻地建议查看我去年制作的演示文稿https://speakerdeck.com/filippovitale/will-it-blend-scalasyd-february-2015
编辑
我们还可以将地图地图的地图显示为Foldable
,并使用foldMap
获得相同的结果:
input.map(_.split(", "))
.foldMap{ case Array(n, g, c, v) => Map(n -> Map(g -> Map(c -> v.toInt))) }
答案 1 :(得分:0)
Filippo Vitale代码更简洁优雅
这是一个强力解决方案:
val t =
"""Bob, Carrots, United States, 200
|Bill, Potatoes, England, 100
|Bob, Oranges, England, 50
|Bob, Carrots, United States, 20""".stripMargin
def commaSplit(s: String) = s.splitAt(s.indexOf(","))
def f(arg: Seq[String]) =
arg
.groupBy(commaSplit(_)._1)
.map{ case (key, values) => key -> values.map(commaSplit(_)._2.drop(2))}
val res =
f(t.split("\n"))
.map{ case (key, values) => key -> f(values).map { case (k, v) =>
k -> f(v).map { case (country, amount) => country -> amount.map(_.toInt).sum }
}}
给出了这个结果:
Map(Bob -> Map(Carrots -> Map(United States -> 220),
Oranges -> Map(England -> 50)),
Bill -> Map(Potatoes -> Map(England -> 100)))