加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读