为了更简洁(尽管以简洁为代价)接近:
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 }
}
示例用法:
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
但是,由于 prices 和 stock 属性紧密相连,而且不同的项目类型在编译时是已知的,您可能需要考虑使用自定义数据结构来表示价格和库存给定的项目。例如。一个符合 Hashable 的项目,以便您的项目可以在 Set 集合中表示。此外,在简单的商店案例中,每个项目都应该是唯一可识别的,因此使用enum 来识别这样的项目是合理的。例如:
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
}
}
在这种情况下,您的商品商店(例如 Store)拥有 Set 的(唯一)商品,这些商品在购买或重新入库(或重新定价)时可能会发生变化:
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 }
}
}
示例用法:
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