Calculating totals from sub lists using Scala
Requirements
Given a list of users' names and permissionIdsI want a total count of each permissionId
So that I can see which permissions are required most frequently
Given the following data about two users (Alice and Bob)...
{"users":[
{"title":"Alice",
"permissionIds":[1,2]
},
{"title":"Bob",
"permissionIds":[2,3]
}
]}
I want to map those users' permsission Ids (1, 2, 3) to each one's count.
permissionId total
1 1
2 2
3 1
Solution
Here's how to accomplish this in Scala:
scala> case class User(name: String, permissionIds: List[Int])
defined class User
scala> val user1 = User("Alice", List(1, 2))
user1: User = User(Alice,List(1, 2))
scala> val user2 = User("Bob", List(2, 3))
user2: User = User(Bob,List(2, 3))
scala> val users = List(user1, user2)
users: List[User] = List(User(Alice,List(1, 2)), User(Bob,List(2, 3)))
scala> val permissionIdTotals = users.map(_.permissionIds).flatten.groupBy(identity).mapValues(_.size)
permissionIdTotals: scala.collection.immutable.Map[Int,Int] = Map(3 -> 1, 1 -> 1, 2 -> 2)
Here's how the permissionIdTotal calculation is broken down:
scala> users.map(_.permissionIds)
res0: List[List[Int]] = List(List(1, 2), List(2, 3))
scala> users.map(_.permissionIds).flatten
res1: List[Int] = List(1, 2, 2, 3)
scala> users.map(_.permissionIds).flatten.groupBy(identity)
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(3 -> List(3), 1 -> List(1), 2 -> List(2, 2))
scala> users.map(_.permissionIds).flatten.groupBy(identity).mapValues(_.size)
res3: scala.collection.immutable.Map[Int,Int] = Map(3 -> 1, 1 -> 1, 2 -> 2)
Retrospective
Note that I did not use variables to store temporary values; It uses a series of chained function calls to arrive at the final calculation.Given a set of input values, the results will always be the same. There are not side effects.
The converse of functional programming is imperative programming.
Imperative programming tends to be easier to understand, but requires more lines of code and may not be safe to use when attempting to satisfy concurrent programming requirements.
No comments:
Post a Comment