i have two data models as below:
class Card {
let type: String
let name: String
let icon: String
init(
type: String,
name: String,
icon: String
) {
self.type = type
self.icon = icon
self.name = name
}
}
class Product {
let type: String? // please watch out here is optional value
let imageUrl: String
let content: String
init(
type: String?,
imageUrl: String,
content: String
) {
self.type = type
self.imageUrl = imageUrl
self.content = content
}
}
And I managed to get the above two entities mapped data with API response, right now I got a new requirement that needs to merge the above two data entities as the following structure. and products be filtered by same type
which included in both Card
and Product
class MergedData {
let type: String // same "type" with "Product.type"
let name: String
let icon: String
let products: [Product] // products inserted here should have same "type"
init(
type: String,
name: String,
icon: String,
products: [Product]
) {
self.type = type
self.icon = icon
self.name = name
self.products = products
}
}
lets say we have a DemoViewModel
here
class DemoViewModel {
var cards: [Card]
var products: [Product]
var mergedData: [MergedData] = []
init(cards: [Card],
products: [Product]) {
self.cards = cards
self.products = products
}
func getMergedData() -> [MergedData] {
// how to write here ?
}
}
how to write the content of getMergedData
?
CodePudding user response:
I would first group the products array on type
and use that for looking up the products for a card
This first solution will only merge data for cards that has matching products
func merge(cards: [Card], with products: [Product]) -> [MergedData] {
let groupedProducts = Dictionary(grouping: products, by: \Product.type)
return cards.compactMap { card in
guard let products = groupedProducts[card.type] else { return nil }
return MergedData(card: card, products: products)
}
}
but if you want to create a MergedData instance for each Card instance you can replace the last part with
return cards.map { card in
let products = groupedProducts[card.type]
return MergedData(card: card, products: products)
}
Note that I created a custom init for this to make the code cleaner
init(card: Card, products: [Product]?) {
type = card.type
icon = card.icon
name = card.name
self.products = products ?? []
}
CodePudding user response:
Try:
func getMergedData() -> [MergedData] {
cards.map{ card in
MergedData(type: card.type, name: card.name, icon: card.icon, products: products.filter{product in product.type == card.type })
}
}
this itterates through all cards creates a new MergedData
for each card and assigns all Product
that have the same type.