-1

I am new to Swift. Recently, I am working on Swift exercises.

Imagine you are creating an app for making purchases. Write a function that will take the name of an item for purchase and will return the cost of that item. In the body of the function, check to see if the item is in stock by accessing it in the dictionary stock. If it is, return the price of the item by accessing it in the dictionary prices. If the item is out of stock, return nil. Call the function and pass in a String that exists in the dictionaries below. Print the return value.

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(prices:String)->(Int?){
    if stock.index(forKey: prices) == nil{
        return nil
    }else{
        for (String,value) in prices{
            return value
        }
    }
}

I try to access the stock dictionary, but I don't know how to return the result of the given string.

The error is:

type 'String' does not conform to protocol 'Sequence'.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
sam
  • 51
  • 4

2 Answers2

0

You are doing it totally wrong. I would suggest you to go through the basics first. The requirement can be met as following

func purchase(item:String)->Double?{
    if let price = prices[item] {
        if let quantity = stock[item] { // check for quantitiy of item
            if quantity == 0 { // item present but 0 quantatiy
                return nil
            }
        } else {
            return nil // item not present in stock
        }
        stock[item] = stock[item]! - 1 // one itme sold
        return price // return the price of the item

    } else {
        return nil // item not present in prices
    }
}
Mohammad Sadiq
  • 5,070
  • 28
  • 29
0

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
dfrib
  • 70,367
  • 12
  • 127
  • 192