I have a nested case
classes structure in a List
for simplicity will use following as an example -
case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, addresses: List[Address])
case class Department(people: List[Person])
say there is List[Department]
; now if I wan to create a new List[Department]
by filtering Address
for each Person
which doesn't have a specific zipCode
value ; traditionally we can do following
def filterPersonsByAddress(dlist: List[Department]): List[Department] = {
dlist.map { d =>
val people = d.people.map { p =>
p.copy(addresses = p.addresses.filterNot(_.zipCode == 38978))}
d.copy(people=people)
}
}
This approach is not performant as depending on the nesting level it can be Big O(n^2) or Big O(n^3) ;
I am trying to learn Lenses via Monocle. So far what I have learned is Lenses is useful when you have to "modify" a deeply nested case
class structure but haven't yet found a way to "chop off" certain part of nested structure based on a condition and return a new structure. Is this possible for via Monocle? Also I am not sure if Lenses will be able to help in achieving better Big O time as well?
The following is essentially equivalent to your implementation in terms of performance, but it's arguable clearer:
import monocle.Traversal, monocle.macros.GenLens
import monocle.function.all._, monocle.std.list._
val deptAddresses: Traversal[Department, List[Address]] =
GenLens[Department](_.people)
.composeTraversal(each)
.composeLens(GenLens[Person](_.addresses))
val filterAddresses: Department => Department =
deptAddresses.modify(_.filterNot(_.zipCode == 38978))
This just builds a traversal to navigate to each person's list of addresses so that you can modify it based on the predicate. I'm not sure there's a better way to perform the filtering (since zip codes don't serve as unique indices), but maybe Julien will weigh in with one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With