从List of case类结构中高效而优雅地移除元素



我在List 中有一个嵌套的case类结构

为了简单起见,将使用以下作为示例-

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])

假设存在CCD_ 3;现在,如果我想通过对没有特定zipCode值的每个Person过滤Address来创建新的List[Department];传统上我们可以按照

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

这种方法不具有性能,因为根据嵌套级别,它可以是大O(n^2)或大O(n ^3);

我正试着通过Monocle学习镜片。到目前为止,我学到的是,当你必须"修改"一个深度嵌套的case类结构,但还没有找到一种方法来根据条件"砍掉"嵌套结构的某些部分并返回一个新结构时,Lenses是有用的。这可能通过Monocle吗?此外,我不确定Lenses是否也能帮助实现更好的大O时间?

就性能而言,以下内容基本上与您的实现等效,但它更清晰:

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

这只是建立了一个遍历来导航到每个人的地址列表,这样您就可以根据谓词对其进行修改。我不确定是否有更好的方法来执行过滤(因为邮政编码不是唯一的索引),但也许Julien会考虑一下。

最新更新