For a more condensed (although at the cost of brevity) approached:
var prices = ["Chips": 2.99, "Donuts": 1.89, "Juice": 3.99, "Apple": 0.50, "Banana": 0.25, "Broccoli": 0.99]
var stock = ["Chips": 4, "Donuts": 0, "Juice": 12, "Apple": 6, "Banana": 6, "Broccoli": 3]
func purchase(item: String) -> Double? {
// item is in stock with a quantity larger than 0
guard (stock[item] ?? 0) > 0 else { return nil }
// return the price for the item (which is in stock), at
// the same time decreasing the stock of the item by 1.
return prices[item].map { stock[item]? -= 1; return $0 }
}
Example usage:
print(stock["Chips"] ?? 0)
purchase(item: "Chips") // 2.99
print(stock["Chips"] ?? 0) // 3
purchase(item: "Chips") // 2.99
purchase(item: "Chips") // 2.99
purchase(item: "Chips") // 2.99
print(stock["Chips"] ?? 0) // 0
purchase(item: "Chips") // nil (out of stock!)
print(stock["Chips"] ?? 0) // 0
However, since the prices
and stock
properties are tightly connected and, moreover, the different item types are known at compile time, you might want to consider using a custom data structure to represent the price and stock of a given item. E.g. one that conforms to Hashable
so that your items can be represented in a Set
collection. Moreover, in the simple store case, each item should be uniquely identifiable, so it could be reasonable to use an enum
to identify such an item. E.g.:
enum ItemIdentifier: Int {
case chips, donuts, juice, apple, banana, broccoli
}
// we design items to be unique, and want (in this simple example)
// to allow updating their properties on-the-fly via subscripting,
// so we design them as reference (class) type.
class Item : Hashable {
let itemIdentifier: ItemIdentifier
var price: Double
var stock: Int
init(_ itemIdentifier: ItemIdentifier, _ price: Double, _ stock: Int) {
self.itemIdentifier = itemIdentifier
self.price = price
self.stock = stock
}
// OBS!
// generally we'd like to define equalness as all-instance-member equality,
// but since items, in this example, are designed to be unique, we will only
// define the equalness of two items as the equalness of their itemIdentifier.
static func ==(lhs: Item, rhs: Item) -> Bool {
return lhs.itemIdentifier == rhs.itemIdentifier
}
var hashValue: Int {
return itemIdentifier.rawValue
}
}
In which case your item store, say Store
, owns a Set
of (unique) items, which may be mutated when an item is bought or re-stocked (or re-priced):
struct Store {
private var items: Set<Item>
init() {
items = Set([Item(.chips, 2.99, 4),
Item(.donuts, 1.89, 0),
Item(.juice, 3.99, 12),
Item(.apple, 0.50, 6),
Item(.banana, 0.25, 6),
Item(.broccoli, 0.99, 3)])
}
subscript(itemIdentifier: ItemIdentifier) -> Item? {
get {
let dummy = Item(itemIdentifier, 0.0, 0)
return items.index(of: dummy).map { items[$0] }
}
}
// ... methods/subscript to add new or update/replace existing items
func purchase(item itemIdentifier: ItemIdentifier) -> Double? {
// item is in stock with a quantity larger than 0
guard (self[itemIdentifier]?.stock ?? 0) > 0 else { return nil }
// return the price for the item (which is in stock), at
// the same time decreasing the stock of the item by 1.
return self[itemIdentifier].map { $0.stock -= 1; return $0.price }
}
}
Example usage:
var store = Store()
print(store[.broccoli]?.stock ?? 0) // 3
store.purchase(item: .broccoli) // 0.99
print(store[.broccoli]?.stock ?? 0) // 2
store.purchase(item: .broccoli) // 0.99
store.purchase(item: .broccoli) // 0.99
print(store[.broccoli]?.stock ?? 0) // 0
store.purchase(item: .broccoli) // nil
store[.broccoli]?.stock += 1