cacert
cacert

Reputation: 2797

Copy objects with collections in scala

I want to clean fields of some objects which are part of collections(setting to None). Below is the class hierarchy and their structures

final case class OrderItem(
                                 simpleSku: String,
                                 merchant: Option[String])
final case class OrderItemGroup(id: String,
                                    items: Seq[OrderItem],
                                    fType: Option[String])
final case class OrderRequest(groups: Seq[OrderItemGroup])

val orderItem1 = OrderItem("simple1",Some("merchant1"))
val salesOrderItem2 = OrderItem("simple2",Some("merchant2"))
val salesOrderItem3 = OrderItem("simple3",Some("merchant3"))
val c1 = OrderItemGroup("id1",Seq(orderItem1,salesOrderItem3),Some("fulfillmentA"))
val c2 = OrderItemGroup("id2",Seq(orderItem1,salesOrderItem2),Some("fulfillmentB"))
val o = OrderRequest(Seq(c1,c2))

I basically want to clean fields merchant and fType and come up with the following code but its multiplying inner items. How can this be done with .copy approach?

def clearFields (orderRequest:OrderRequest) :OrderRequest = {
  val items = orderRequest.groups.flatMap(x => x.items)
  println("items" + items)
  val groups = orderRequest.groups
  val r = orderRequest.copy(groups = groups.map(_.copy(fType = None, items = items.map(_.copy(merchant = None)))))
  r
}

Upvotes: 0

Views: 55

Answers (1)

Mario Galic
Mario Galic

Reputation: 48420

Monocle is helpful when we have to copy such nested structures, for example,

import monocle.Traversal
import monocle.macros.GenLens
import cats.implicits._ 

val cleanMerchant = GenLens[OrderItem](_.merchant).set(None)
val cleanFType = GenLens[OrderItemGroup](_.fType).set(None)
val cleanGroupItems = Traversal.fromTraverse[List, OrderItemGroup].modify(g => g.copy(items = g.items.map(cleanMerchant)))

OrderRequest(cleanGroupItems(o.groups.toList).map(cleanFType))

outputs

OrderRequest(List(OrderItemGroup(id1,List(OrderItem(simple1,None), OrderItem(simple3,None)),None), OrderItemGroup(id2,List(OrderItem(simple1,None), OrderItem(simple2,None)),None)))

To clean it using vanilla Scala try

def cleanOrderItemGroup(group: OrderItemGroup): OrderItemGroup = {
  val items = group.items
  val cleanItems = items.map(cleanOrderItem)
  group.copy(items = cleanItems, fType = None)
}

def cleanOrderItem(item: OrderItem): OrderItem = {
  item.copy(merchant = None)
}

OrderRequest(o.groups.map(cleanOrderItemGroup))

which again outputs

OrderRequest(List(OrderItemGroup(id1,List(OrderItem(simple1,None), OrderItem(simple3,None)),None), OrderItemGroup(id2,List(OrderItem(simple1,None), OrderItem(simple2,None)),None)))

Upvotes: 3

Related Questions