gpt4 book ai didi

scala - 如何使用 "Seq"字段修改此嵌套案例类?

转载 作者:行者123 更新时间:2023-12-04 09:14:00 25 4
gpt4 key购买 nike

一些嵌套的案例类,字段addressesSeq[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
}
}))
}))

然后, modified员工为:
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(Bbb street)),
    Address(Street(Bpp street))
    )
    )
    )

    请注意,与Shapeless答案一样,您需要更改 Employee定义以使用 List而不是 Seq,或者,如果您不想更改模型,则可以使用 Lens将该转换构建到 Iso[Seq[A], List[A]]中。

    关于scala - 如何使用 "Seq"字段修改此嵌套案例类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33261264/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com