过滤对象数组并在Swift中求和它们的属性

时间:2016-07-15 08:50:49

标签: ios arrays swift core-data

我想从一系列产品中生成购物清单。 我有一个实体"产品"在Core Data中,其名称(String)和amount(Int)作为其属性。我现在正处于一系列产品中,有一些副本,类似的东西:

var products : [Product] = [Apple, Egg, Orange, Apple, Orange, Banana, Egg, Egg]

如何过滤此类数组以获取特定产品数量的总和?我希望得到的产品列表的数量为:Apple: 4, Banana: 3, Egg: 7, Orange 2。我知道我可以从该阵列中制作一个Set以避免重复,但我不知道如何对产品进行求和'之前的金额。

3 个答案:

答案 0 :(得分:3)

enum Product {
    case Apple
    case Egg
    case Orange
    case Banana
}

let products: [Product] = [.Apple, .Egg, .Orange, .Apple, .Orange, .Banana, .Egg, .Egg]

products.reduce([:]) { (map, product) -> [Product: Int] in
    var updatedMap = map
    if let value = map[product] {
        updatedMap[product] = value + 1
    }
    else {
        updatedMap[product] = 1
    }
    return updatedMap
} //[Orange: 2, Apple: 2, Egg: 3, Banana: 1]

与字符串相同:

let products: [String] = ["Apple", "Egg", "Orange", "Apple", "Orange", "Banana", "Egg", "Egg"]

products.reduce([:]) { (map, product) -> [String: Int] in
    var updatedMap = map
    if let value = map[product] {
        updatedMap[product] = value + 1
    }
    else {
        updatedMap[product] = 1
    }
    return updatedMap
} // ["Apple": 2, "Egg": 3, "Orange": 2, "Banana": 1]

或扩展所有可清除序列类型:

extension SequenceType where Generator.Element: Hashable {
    func countElements() -> [Generator.Element : Int] {
        return reduce([:]) { (map, element) -> [Generator.Element : Int] in
            var updatedMap = map
            if let value = map[element] {
                updatedMap[element] = value + 1
            }
            else {
                updatedMap[element] = 1
            }
            return updatedMap
        }
    }
}

products.countElements() //["Apple": 2, "Egg": 3, "Orange": 2, "Banana": 1]

答案 1 :(得分:0)

enum Fruit {
    case Orange
    case Lemon
    case Potato
}

let fruits = [Fruit.Orange, .Lemon, .Potato, .Orange, .Lemon, .Orange]

var result: [Fruit: Int] = [:]

for fruit in fruits {
    if let count = result[fruit] {
        result[fruit] = count + 1
    }
    else {
        result[fruit] = 1
    }
}

print(result)

--output:--
[Fruit.Potato: 1, Fruit.Orange: 3, Fruit.Lemon: 2]

或者,甚至:

num Product {
    case Apple
    case Egg
    case Orange
    case Banana
}

let products: [Product] = [.Apple, .Egg, .Orange, .Apple, .Orange, .Banana, .Egg, .Egg]

let result = products.reduce([:]) { (var map, product) -> [Product: Int] in
    if let count = map[product] {
        map[product] = count + 1
    }
    else {
        map[product] = 1
    }

    return map
}

print(result)

--output:--
[Product.Orange: 2, Product.Apple: 2, Product.Egg: 3, Product.Banana: 1]

答案 2 :(得分:-1)

你可以这样做:

enum Fruit {
  case Orange
  case Lemon
  case Potato
}

let fruits = [Fruit.Orange, .Lemon, .Potato, .Orange, .Lemon, .Orange]
let fruitSet = Set(fruits)
var result = [Fruit: Int]()

for fruit in fruitSet {
  result[fruit] = fruits.filter { $0 == fruit }.count
}
有人请解释为什么我的答案没用? 输出将是[Fruit.Orange:3,Fruit.Lemon:2,Fruit.Potato:1]