Creating and storing cards cards cards ... in scala

I have a file containing data on Salesman, Product, Location, SalesValue

For instance:

Bob, Carrots, United States, 200 Bill, Potatoes, England, 100 Bob, Oranges, England, 50 Bob, Carrots, United States, 20 

SalesValue can be neatly accumulated into a hash hash hash in perl using the following code

 while(<>){ @cols = split(/,/); $vals {$cols[0]} {$cols[1]} {$cols[2]} += $cols[3]; } 

Does anyone have any suggestions on how this card creation card cards, as well as accumulation, would be best implemented in scala?

+5
source share
2 answers

I suggest seeing the merge of these cards as a monoid-append operation.

First, we create card maps cards as separate elements:

 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 is of type List[Map[String, Map[String, Map[String, Int]]]] :

  List[Map[String, Map[String, Map[String, Int]]]] 

Then we could suml use a library like scalaz or cats :

 import scalaz._, Scalaz._ println(mmm.suml) 

This will print (not identifiable):

 Map(Bill -> Map(Potatoes -> Map(England -> 100)), Bob -> Map(Oranges -> Map(England -> 50), Carrots -> Map(United States -> 220))) 

To understand what is going on with the .suml operation, I would shamelessly offer to check out this presentation I made last year https://speakerdeck.com/filippovitale/will-it-blend-scalasyd-february-2015


EDIT

We can also see our map display maps as Foldable and use foldMap for the same result:

 input.map(_.split(", ")) .foldMap{ case Array(n, g, c, v) => Map(n -> Map(g -> Map(c -> v.toInt))) } 
+6
source

Filippo Vitale codes are more concise and elegant

This is a brute force solution:

 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 } }} 

which gives this result:

 Map(Bob -> Map(Carrots -> Map(United States -> 220), Oranges -> Map(England -> 50)), Bill -> Map(Potatoes -> Map(England -> 100))) 
0
source

Source: https://habr.com/ru/post/1240668/


All Articles