Grant Emerson

Let’s Build an Invisible Wall

Let’s Build an Invisible Wall — SwiftMoji Entry #4

Sometimes it is convenient to divide a Collection based on some sort of condition. Luckily, Swift provides the partition(by:) method on Collections to do just that. The by argument to be passed in as the belongsInSecondPartition parameter is a closure with an Element input type and Bool return type. This closure is used to re-order the collection into two halves: one which doesn’t match the specification and subsequently, one that matches. Interestingly, the partition(by:) method has a return type of Int. This number represents the index of the second partition. If the second partition is empty the endIndex of the collection is returned. This method is utilized in the code example below to reorganize a user’s shopping cart based on the isNecessary property of the Item Elements. This allows the user to purchase all the Items that they can afford without neglecting any of the necessities.

struct Item {
    let name: String
    let isNecessary: Bool
    let price: Int
}

var 🛒 = [
    Item(name: "📱", isNecessary: false, price: 600),
    Item(name: "🧻", isNecessary: true, price: 10),
    Item(name: "🍎", isNecessary: true, price: 5),
    Item(name: "🎮", isNecessary: false, price: 50),
    Item(name: "💡", isNecessary: true, price: 25),
    Item(name: "🍪", isNecessary: false, price: 7)
]

🛒.partition { !$0.isNecessary }

var money = 300

while !🛒.isEmpty && (money - 🛒[0].price) >= 0 {
    let item = 🛒.removeFirst()
    money -= item.price
    print("Bought: \(item.name) for $\(item.price). Total: $\(money)")
}

// Bought: 💡 for $25. Total: $275
// Bought: 🧻 for $10. Total: $265
// Bought: 🍎 for $5. Total: $260
// Bought: 🎮 for $50. Total: $210
Tagged with: