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

Posted

技术标签:

【中文标题】在 Swift 中过滤对象数组并求和它们的属性【英文标题】:Filter array of objects and sum their properties in Swift 【发布时间】:2016-07-15 08:50:49 【问题描述】:

我想从一系列产品中生成购物清单。 我在核心数据中有一个实体“产品”,其属性为名称(字符串)和数量(整数)。我现在有一系列产品,其中有一些重复,类似这样:

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

如何过滤此类数组以获得特定产品数量的总和?因此,我想获得数量如下的产品列表:Apple: 4, Banana: 3, Egg: 7, Orange 2。我知道我可以从该数组中创建一个 Set 以避免重复,但在此之前我不知道如何汇总产品的数量。

【问题讨论】:

为什么你有一个带有欺骗的数组?添加到数组时为什么不合并? 【参考方案1】:
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]

【讨论】:

【参考方案2】:
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]

【讨论】:

【参考方案3】:

你可以这样做:

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]

【讨论】:

假设您有一个包含 100 万个元素的数组,其中包含 20,000 种不同的水果。你的算法需要遍历 100 万个元素的数组多少次? 你必须有一个大家庭 7stud.... 问题是关于购物清单。 :)

以上是关于在 Swift 中过滤对象数组并求和它们的属性的主要内容,如果未能解决你的问题,请参考以下文章

PHP 过滤对象数组并返回新的对象数组,同时基于一个属性删除重复项

过滤具有特定属性 Swift 的 json 数组

在Swift中使用Realm进行过滤,给我一个对象数组,但是当打印一个属性时,它会给我一个空字符串

ES6通过数组中的对象属性求和

如何在Ruby中对数组中对象的属性求和

用于多重过滤 Swift 的布尔语句