2

I would like to generate a shopping list from an array of products. I have an entity "Product" in Core Data that has name (String) and amount (Int) as its properties. I am in the moment where I have an array of products with some duplicates, something like that:

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

How can I filter such array to get sums of amount of specific products? I would like to get as a result the list of products with their amounts like: Apple: 4, Banana: 3, Egg: 7, Orange 2. I know that I can make a Set from that Array to avoid duplicates, but I don't know how to sum products' amount before that.

1
  • 1
    why do you have an array with dupes? why don't you merge when you add to the array ? Commented Jul 15, 2016 at 8:58

3 Answers 3

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]

same with strings:

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]

Or by extension for all hashable sequence types:

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]
Sign up to request clarification or add additional context in comments.

Comments

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]

Or, even:

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]

Comments

-1

You can do like this:

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
}

someone please explain why my answer is not useful? The output will be [Fruit.Orange: 3, Fruit.Lemon: 2, Fruit.Potato: 1]

2 Comments

Let's say you have an array that has 1 million elements containing 20,000 different fruits. How many times would your algorithm have to traverse the 1 million element array?
You must have a big household 7stud.... The question was about a shopping list. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.