Swift - 对列表项进行分组和排序

Swift - Grouping and Ordering List Items

各位开发者。我有一家商店,我需要在其中打印按商品类别分组的每个客户购买清单。请考虑以下代码以进行分组和排序:

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
---------------------------------------------------
*/

你可以找到很多方法来实现它。一种方法是创建分组 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: {[=10=].category()})
            groceryItemsByCategory.sorted{[=10=].key < .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 中的简单编码规则:仅类型名称以大写字母开头。