Суммируйте уникальные комбинации предметов в массиве Swift 4 - PullRequest
0 голосов
/ 02 октября 2018

Я создаю следующий объект:

class Order {
    var productId : Int
    var userId : Int
    var qty : Int
    init(productId: Int, userId: Int, qty: Int) {
        self.productId = productId
        self.userId = userId
        self.qty = qty
    }
}

Затем я создал следующий массив:

var arrayOfOrders = [Order(productId: 1, userId: 1, qty: 5),
                     Order(productId: 1, userId: 2, qty: 10),
                     Order(productId: 1, userId: 2, qty: 15),
                     Order(productId: 2, userId: 1, qty: 20),
                     Order(productId: 2, userId: 1, qty: 10),
                     Order(productId: 2, userId: 2, qty: 5),
                     Order(productId: 3, userId: 1, qty: 15),
                     Order(productId: 3, userId: 1, qty: 5)]

Мне нужно получить уникальную комбинацию productID и userID и суммировать количество вновый массив [Order], подобный этому:

enter image description here

Можно ли использовать функции более высокого порядка, такие как Reduce или Map?Любой другой простой подход был бы очень полезным.Заранее благодарен за помощь

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Вот забавный способ (возможно, немного глупый).Во-первых, измените ваш класс на Hashable структуру (это Swift 4.2 или более поздняя версия), где равенство не зависит от qty, например так:

struct Order : Hashable {
    static func ==(lhs:Order,rhs:Order) -> Bool {
        return lhs.productId == rhs.productId && lhs.userId == rhs.userId
    }
    func hash(into hasher: inout Hasher) {
        productId.hash(into:&hasher)
        userId.hash(into:&hasher)
    }
    // ... and the rest is as before
}

Теперь поместите ордера в набор, таким образом расстановив их., при изменении qty на 0:

var set = Set(arrayOfOrders.map { order -> Order in
    var order = order
    order.qty = 0
    return order
})

Теперь это быстрый одиночный проход для суммирования значений qty в Set:

arrayOfOrders.forEach { order in
    if var totalOrder = set.remove(order) {
        totalOrder.qty += order.qty
        set.insert(totalOrder)
    }
}

Result (set):

[Order(productId: 1, userId: 2, qty: 25), 
Order(productId: 2, userId: 1, qty: 30), 
Order(productId: 1, userId: 1, qty: 5), 
Order(productId: 3, userId: 1, qty: 20), 
Order(productId: 2, userId: 2, qty: 5)]
0 голосов
/ 02 октября 2018
struct Key: Hashable
{
    var userId: Int
    var productId: Int
}

// 1. Group by Key (userId, productId)
let grouped = Dictionary(grouping: arrayOfOrders) { o in
    Key(userId: o.userId, productId: o.productId)
}

// 2. Add up each group's quantity
let summed = grouped.map { group -> Order in
    let qty = group.value.reduce(0) { (qty,order) in
        qty + order.qty
    }
    return Order(productId: group.key.productId,
          userId: group.key.userId,
          qty: qty)
}

Обратите внимание на сходство с действиями SQL GROUP BY / агрегатных функций, например:

SELECT UserId, ProductId, SUM(Qty) 
FROM Orders
GROUP BY UserId, ProductId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...