如何在Swift 5中按键属性从字典中查找总计
如何从如何在Swift 5中按键属性从字典中查找总计,swift,Swift,如何从[Product:Double]的字典中找到品牌的总计 产品具有属性品牌 let items = [Item] let productTotals = items.reduce([Product:Double()) {(result, item in var result = result let product = item.product // Calculate the total product width result[product] = product
[Product:Double]
的字典中找到品牌的总计
产品
具有属性品牌
let items = [Item]
let productTotals = items.reduce([Product:Double()) {(result, item in
var result = result
let product = item.product
// Calculate the total product width
result[product] = product.width * item.count
return result
}
// Now find the totals for each brand by summing the values for Product.brand
let groupTotals = productTotals ???
范例
items = [{ix = 1, product = A, count = 1}, {ix = 2, product = B, count = 2}, {ix = 3, product = C, count = 2}]
products = [{name = 'A', width = 1.0, brand = 'BA'}, {name = 'B', width = 2.0, brand = 'BA'}, {name = 'C', width = 1.0, brand = 'BB'}]
productWidths = [(A: 1), (B: 4), (C: 2)]
brandWidths = [(BA: 5), (BB: 2)]
您可以使用Dictionary(grouping:by:)
对项目进行分组,然后使用mapValue
以所需的方式变换组
我认为有两种方法可以做到这一点。第一个更像您的方式,只是我使用了标准库函数来实现您对产品总数所做的操作
let items = [Item]()
let products = items.map { $0.product }
// This is your "productTotals"
let productTotalWidths = Dictionary(uniqueKeysWithValues:
products.lazy.map { (product: Product) -> (key: Product, value: Double) in
let totalWidth = product.width * product.count
return (key: product, value: totalWidth)
}
)
let productTotalWidthsBrand = Dictionary(grouping: productTotalWidths, by: { $0.key.brand })
.mapValues { (pairs: [(key: Product, value: Double)]) -> Double in
return pairs
.lazy // don't allocate intermediate array
.map { $0.value } // pull out the totalWidths calculates earlier
.reduce(0, +) // sum them
}
但是,正如您所看到的,第二步变得更难了,因为您需要重新组合字典(从按产品
分组,到按品牌
分组),这涉及到扁平化内部组(按产品
分组)
这可以通过先按品牌分组,然后再进行其他操作来简化:
let items = [Item]()
let products = items.map { $0.product }
let productsByBrand = Dictionary(grouping: products, by: { $0.brand })
let productTotalWidthsByBrand = productsByBrand.mapValues { products in
return products
.lazy // don't allocate an intermediate array
.map { $0.width * $0.count } // calc total width per product
.reduce(0, +) // sum them
}
扩展@matt的建议-我不知道你可以设定一个默认值,我忘记了同一个产品可能会出现多次
let productSpace = items.reduce(into: [Product:Double]()) { result, item in
if let product = item.product {
result[product, default: 0.0] += product.width * item.count
}
}
let brandSpace = productsSpace.reduce(into: [Brand:Double]()) { result, productSpace in
if let brand = productSpace.key.brand {
result[brand, default: 0.0] += productSpace.value
}
}
你能给我们一个完整的、可编译的例子和一些样本数据吗?使用reduce(into:)
形成一个直方图。@matt更多细节或例子?@Alexander-Monica-如果我能做到这一点,我就不会问items=[{ix=1,product=a,count=1},
不是有效的Swift。谢谢,不太清楚,因为$0.count实际上是该商品的一个属性。因此,按品牌分组的产品会丢失该商品,因此您无法进行计算。我认为@matts建议可能更简单-请参阅我的答案。$0.count实际上是该商品的一个属性
,这正是我要求的原因一个可比较的例子。我不是要一个可比较的解决方案,而是一个让我们开始的测试夹具,所有正确的数据类型<代码>项目<代码>,<代码>产品<代码>,<代码>品牌<代码>,等等,还有一些示例数据和一些预期结果。如果没有这些,我们就只能玩评论乒乓球,猜测你不清楚的cri泰里亚。