在Array Swift 4中总结独特的项目组合

时间:2018-10-02 14:39:39

标签: swift

我创建以下对象:

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 :(得分:2)

base
[a,c]
[c,e]
[a,h]

请注意与使用SQL GROUP BY /聚合函数的相似之处,

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

答案 1 :(得分:0)

这是一种有趣的方式(也许有点愚蠢)。首先,将您的类更改为不依赖于pacman -S的Hashable结构(这是Swift 4.2或更高版本),如下所示:

awk '{print "pacman -S " $0;}' tmp.txt > file1.txt

现在将订单放入集合中,从而对它们进行唯一化,同时将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):

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