scala – 如何使用“Seq”字段修改此嵌套案例类?
发布时间:2020-12-16 08:50:55 所属栏目:安全 来源:网络整理
导读:一些嵌套的case类和字段地址是Seq [Address]: // ... means other fieldscase class Street(name: String,...)case class Address(street: Street,...)case class Company(addresses: Seq[Address],...)case class Employee(company: Company,...) 我有一名
一些嵌套的case类和字段地址是Seq [Address]:
// ... means other fields case class Street(name: String,...) case class Address(street: Street,...) case class Company(addresses: Seq[Address],...) case class Employee(company: Company,...) 我有一名员工: val employee = Employee(Company(Seq( Address(Street("aaa street")),Address(Street("bbb street")),Address(Street("bpp street"))))) 它有3个地址. 而且我想把街道开头只用“b”开头.我的代码很乱如下: val modified = employee.copy(company = employee.company.copy(addresses = employee.company.addresses.map { address => address.copy(street = address.street.copy(name = { if (address.street.name.startsWith("b")) { address.street.name.capitalize } else { address.street.name } })) })) 修改后的员工是: Employee(Company(List( Address(Street(aaa street)),Address(Street(Bbb street)),Address(Street(Bpp street))))) 我正在寻找一种方法来改进它,但却找不到一种方法.甚至尝试了Monocle,但无法将其应用于此问题. 有没有办法让它变得更好? PS:有两个关键要求: >仅使用不可变数据 解决方法
正如Peter Neyens指出的那样,Shapeless的SYB在这里运行得非常好,但它会修改树中的所有Street值,这可能并不总是你想要的.如果您需要更多控制路径,Monocle可以提供帮助:
import monocle.Traversal import monocle.function.all._,monocle.macros._,monocle.std.list._ val employeeStreetNameLens: Traversal[Employee,String] = GenLens[Employee](_.company).composeTraversal( GenLens[Company](_.addresses) .composeTraversal(each) .composeLens(GenLens[Address](_.street)) .composeLens(GenLens[Street](_.name)) ) val capitalizer = employeeStreeNameLens.modify { case s if s.startsWith("b") => s.capitalize case s => s } 正如Julien Truffaut在编辑中指出的那样,通过创建一个镜头一直到街道名称的第一个角色,你可以使这更加简洁(但不那么通用): import monocle.std.string._ val employeeStreetNameFirstLens: Traversal[Employee,Char] = GenLens[Employee](_.company.addresses) .composeTraversal(each) .composeLens(GenLens[Address](_.street.name)) .compoSEOptional(headOption) val capitalizer = employeeStreetNameFirstLens.modify { case 'b' => 'B' case s => s } 有一些符号运算符会使上面的定义更加简洁,但我更喜欢非符号版本. 然后(结果重新格式化以便清晰): scala> capitalizer(employee) res3: Employee = Employee( Company( List( Address(Street(aaa street)),Address(Street(Bpp street)) ) ) ) 请注意,在Shapeless答案中,您需要将Employee定义更改为使用List而不是Seq,或者如果您不想更改模型,则可以使用Iso构建转换到Lens [Seq [ A],列表[A]]. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |