合并对象数组

时间:2018-11-16 11:17:41

标签: ios arrays swift sorting generics

有没有有效的方法来合并对象数组?我有一个模型[sales],它有saleAmount, soldBy。可能有多个由不同客户出售的商品。所以我想要的是,如果说,例如ABC出售的物品,那么我想对ABC出售的saleAmount求和。下面是一个示例。

class Sale  {

    var soldBy : String = "" 
    var saleAmount : Double = 0.00
}
var sales : [sale] = [sale]()

sales array contains:
[
["ABC", 1200.34],
["ABC", 999.34],
["ABC", 3499.99],
["DEF", 333.32],
["DEF", 778.12]
]

Expected output :
[["ABC", 5699.67],
["DEF" , 1111.44]]

5 个答案:

答案 0 :(得分:2)

具有:

struct Sales {
    let name: String
    let amount: Float

    init(name: String, amount: Float) {
        self.name = name
        self.amount = amount
    }
}

我将添加:

extension Sales {
    init(withSales initialSales: Sales, otherSale: Sales) {
        self.init(name: initialSales.name, amount: initialSales.amount + otherSale.amount)
    }
}

我将使用reduce(into:_:)

let sales: [Sales] = [Sales(name: "ABC", amount: 1200.34),
                      Sales(name: "ABC", amount: 999.34),
                      Sales(name: "ABC", amount: 3499.99),
                      Sales(name: "DEF", amount: 333.32),
                      Sales(name: "DEF", amount: 778.12)]

let reducedSale = sales.reduce(into: [Sales]()) { (currentResult, current) in
    if let existingSalesIndex = currentResult.firstIndex(where: { $0.name == current.name }) {
        let existingSale = currentResult[existingSalesIndex]
        currentResult[existingSalesIndex] = Sales(withSales: existingSale, otherSale: current)

    } else {
        currentResult.append(current)
    }
}

print("reducedSales: \(reducedSales: [AppName.Sales(name: "ABC", amount: 5699.67), AppName.Sales(name: "DEF", amount: 1111.44)])

由于使用了类,因此可以避免方便的初始化,而只需添加金额即可。

答案 1 :(得分:2)

销售类别:

class Sale{
        var soldBy:String
        var amount:Double

        init(soldBy:String, amount:Double) {
            self.soldBy = soldBy
            self.amount = amount
        }
}

计算输出:

let output = sales.reduce([String:Double]()) { (result, sale) -> [String:Double] in
        var result = result
        result[sale.soldBy, default: 0.0] += sale.amount
        return result
}

参考: https://developer.apple.com/documentation/swift/dictionary/2925471-reduce

答案 2 :(得分:1)

您可以根据销售创建一系列键/值对,然后 使用Dictionary(_:uniquingKeysWith:) 用唯一键和总和创建字典 相应的值:

struct Sale  {
    let soldBy: String
    let saleAmount: Double
}

let sales = [
    Sale(soldBy: "ABC", saleAmount: 1200.34),
    Sale(soldBy: "ABC", saleAmount: 999.34),
    Sale(soldBy: "ABC", saleAmount: 3499.99),
    Sale(soldBy: "DEF", saleAmount: 333.32),
    Sale(soldBy: "DEF", saleAmount: 778.12),
]

let sums = Dictionary(sales.map { ($0.soldBy, $0.saleAmount) },
                      uniquingKeysWith: { $0 + $1 })

print(sums)
// ["ABC": 5699.67, "DEF": 1111.44]

然后您可以根据字典创建一系列销售:

let sumSales = sums.map { Sale(soldBy: $0.key, saleAmount: $0.value) }

print(sumSales)
// [Sale(soldBy: "ABC", saleAmount: 5699.67), Sale(soldBy: "DEF", saleAmount: 1111.44)]

出于演示目的,我假设Sale结构。

答案 3 :(得分:1)

您可以使用Dictionary(grouping:by:)

let groupedSales: [Sale] = Dictionary(grouping: sales) { $0.soldBy }
    .lazy
    .map { element in
        let sum = element.value.lazy.map { $0.saleAmount }.reduce(0,+)
        //Or as suggested by Mr Martin: let sum = element.value.reduce(0, { $0 + $1.saleAmount })
        return Sale(soldBy: element.key, saleAmount: sum)
    }

现在您可以打印结果了:

for s in groupedSales {
    print(s.soldBy, s.saleAmount)
}
//ABC 5699.67
//DEF 1111.44

为方便起见,我已将此初始化程序添加到Sale类中:

class Sale  {
    var soldBy : String = ""
    var saleAmount : Double = 0.00

    init(soldBy: String, saleAmount: Double) {
        self.soldBy = soldBy
        self.saleAmount = saleAmount
    }
}

答案 4 :(得分:0)

从@DaniyalRaza的答案开始,并进行一些清理:

readAsArrayBuffer