Массив клубных объектов - PullRequest
0 голосов
/ 16 ноября 2018

Есть ли эффективный способ объединения массивов объектов?У меня есть модель [sales], которая имеет saleAmount, soldBy.Там может быть несколько предметов, проданных разными клиентами.Так что я хотел, чтобы, если товары, продаваемые, скажем, ABC, то я хотел бы суммировать продажную сумму, проданную ABC.Пример приведен ниже.

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 голосов
/ 16 ноября 2018

Начиная с ответа @ DaniyalRaza и заканчивая уборкой:

class Sale: CustomStringConvertible {
    var soldBy:String
    var amount:Double

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

    //This lets us use string interpolation to display a `Sale` object
    var description: String {
        return "Sale(soldBy:\"\(soldBy)\",amount:\(amount)"
    }
}

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


let output: [Sale] = sales.reduce([String:Double]()) { (result, sale) -> [String:Double] in
    var result = result
    result[sale.soldBy, default: 0.0] += sale.amount
    return result
}
    //Map the dictionary from the above back to an array
    .map { Sale(soldBy: $0.key, amount: $0.value) }

    //Sort the output back into alphabetical order by soldBy (if desired)
    //Note that sorting will take time, so only do this step if needed.
    .sorted { $0.soldBy < $1.soldBy }

print(output)
0 голосов
/ 16 ноября 2018

Вы можете использовать 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
    }
}
0 голосов
/ 16 ноября 2018

Вы можете создать последовательность пар ключ / значение из продаж и использовать 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 является структурой.

0 голосов
/ 16 ноября 2018

Класс продажи:

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

0 голосов
/ 16 ноября 2018

Имея:

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

Поскольку вы используете класс, вы можете избежать удобства инициализации и просто добавить сумму.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...