Swift - 分组和排序列表项

时间:2018-03-25 11:49:36

标签: ios arrays swift dictionary predicate

研究员。我有一个商店,我需要打印按项目类别分组的每个客户购买清单。请考虑以下代码以进行分组和排序:

protocol GroceryItem{
    func cost () -> Float
    func description() -> String
    func category() -> String

}

  struct GroceryStore {

    func printReceit(customer: [Customer])  {

        customer.forEach { (client) in
            print("---------------------------------------------------")
            print("     Printing Receipt for Customer: \(client.name)")
            var total: Float = 0
            print("---------------------------------------------------")
            client.groceryList.forEach({ (item) in
                if let groceryItem = item as? GroceryItem {
                    print("******** \(groceryItem.category())")
                    print("                 \(groceryItem.description())")
                    total += groceryItem.cost()
                }
            })
            print("Total: \(total)")
            print("---------------------------------------------------")
        }

    }
}

enum Category: String {
    case Fruits
    case Vegetables
    case Dairies
    case Meats
    case Fishes
    case Drinks
    case Others
}

enum Unit: String {
    case Kg
    case Lt
    case Un
}

struct Customer{
    let name: String
    let groceryList: [Any]
}

struct Product: GroceryItem {

    let categ: Category
    let name: String
    let price: Float
    let qty: Float
    let unit: Unit

    func cost() -> Float {
        return price
    }
    func description() -> String {
        return "\(name): \(price)"
    }
    func category() -> String {
        return categ.rawValue
    }
}


// Store
let Walmart = GroceryStore()

// Store Products
let strawberry = Product(categ: .Fruits, name: "Strawberry", price: 1.75, qty: 1, unit: .Kg)
let apple = Product(categ: .Fruits, name: "Apple", price: 100, qty: 1.45, unit: .Un)
let pear = Product(categ: .Fruits, name: "Pear", price: 120, qty: 1.50, unit: .Un)
let hamburguer = Product(categ: .Meats, name: "Hamburguer", price: 750, qty: 1.5, unit: .Kg)
let parmesan = Product(categ: .Dairies, name: "Parmesan", price: 1000, qty: 2, unit: .Kg)
let milk = Product(categ: .Dairies, name: "Milk", price: 150, qty: 2, unit: .Lt)
let yogurt = Product(categ: .Dairies, name: "Danone", price: 300, qty: 1, unit: .Un)
let yogurt2 = Product(categ: .Dairies, name: "Oikos", price: 1000, qty: 2, unit: .Un)
let drink = Product(categ: .Drinks, name: "Fanta", price: 600, qty: 1.5, unit: .Lt)
let meat = Product(categ: .Meats, name: "Angus", price: 4000, qty: 5.0, unit: .Kg)
let drink2 = Product(categ: .Drinks, name: "Compal", price: 350, qty: 1, unit: .Un)

// Customers
let yasmin = Customer(name: "Yasmin", groceryList: [apple, hamburguer, milk, yogurt, drink])
let camila = Customer(name: "Camila", groceryList: [pear, parmesan, milk, yogurt2, meat, drink2])

Walmart.printReceit(customer: [yasmin, camila])

哪个输出:

/*
---------------------------------------------------
     Printing Receipt for Customer: Yasmin
---------------------------------------------------
******** Fruits
                 Apple: 100.0
******** Meats
                 Hamburguer: 750.0
******** Dairies
                 Milk: 150.0
******** Dairies
                 Danone: 300.0
******** Drinks
                 Fanta: 600.0
Total: 1900.0
---------------------------------------------------
---------------------------------------------------
     Printing Receipt for Customer: Camila
---------------------------------------------------
******** Fruits
                 Pear: 120.0
******** Dairies
                 Parmesan: 1000.0
******** Dairies
                 Milk: 150.0
******** Dairies
                 Oikos: 1000.0
******** Meats
                 Angus: 4000.0
******** Drinks
                 Compal: 350.0
Total: 6620.0
---------------------------------------------------
*/

但是所需的输出应该是这样的,即:按字母顺序排序并按类别分组的产品。我怎样才能做到这一点?:

/*
---------------------------------------------------
     Printing Receipt for Customer: Camila
---------------------------------------------------
******** Dairies ********************************
                Milk: 150.0
                Oikos: 1000.0
                Parmesan: 1000.0

******** Drinks ********************************
                Compal: 350.0

******** Fruits ********************************
                Pear: 120.0

******** Meats ********************************
                Angus: 4000.0

Total: 6620.0
---------------------------------------------------
*/

1 个答案:

答案 0 :(得分:3)

您可以找到许多方法来实现它。一种方法是创建分组Dictionary

struct GroceryStore {

    func printReceit(customer: [Customer])  {

        customer.forEach { (client) in
            print("---------------------------------------------------")
            print("     Printing Receipt for Customer: \(client.name)")
            var total: Float = 0
            print("---------------------------------------------------")
            //Creating a grouped Dictionary
            let groceryItemsByCategory = Dictionary(grouping: client.groceryList, by: {$0.category()})
            groceryItemsByCategory.sorted{$0.key < $1.key}.forEach {entry in
                let (key, groceryItems) = entry
                print("******** \(key) ********************************")
                groceryItems.forEach {groceryItem in
                    print("                 \(groceryItem.description())")
                    total += groceryItem.cost()
                }
            }
            print("Total: \(total)")
            print("---------------------------------------------------")
        }

    }
}

我稍微修改了你的代码以简化:

struct Customer{
    let name: String
    let groceryList: [GroceryItem]
}

如果此更改不符合您的要求,您可能需要更多演员表或类型检查。

我保留了所有其他部分,但最好在Swift中保留简单的编码规则:只有类型名称以大写字母开头。