2016-07-15 2 views
2

Я хотел бы создать список покупок из массива продуктов. У меня есть объект «Продукт» в Core Data, который имеет имя (String) и количество (Int) в качестве своих свойств. Я в тот момент, когда у меня есть множество продуктов с некоторыми дубликатами, что-то вроде этого:Фильтровать массив объектов и суммировать их свойства в Swift

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

Как я могу фильтровать такой массив, чтобы получить суммы количества определенных продуктов? Я хотел бы получить в результате список продуктов с их суммами, такими как: Apple: 4, Banana: 3, Egg: 7, Orange 2. Я знаю, что я могу сделать набор из этого массива, чтобы избежать дубликатов, но я не знаю, как суммировать сумму продуктов до этого.

+1

почему у вас есть массив с простаков? почему бы вам не объединиться при добавлении в массив? – Wain

ответ

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] 

Или расширения для всех hashable типов последовательности:

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

Вы можете сделать так:

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]

+1

Предположим, у вас есть массив с 1 миллионом элементов, содержащий 20 000 различных фруктов. Сколько раз ваш алгоритм должен пересечь 1 миллионный массив элементов? – 7stud

+0

У вас должен быть большой дом 7stud .... Вопрос был о списке покупок. :) – GOR

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] 
Смежные вопросы