假设在我们开发一个商品页面的时候,需求是按商品的分类来分 section,但后台给我们返回的数据是整个列表的商品数组。在 Swift 5 之前,我们只能通过遍历数组来分组:
struct Shop { let name: String let category: String } let shops = [Shop(name: "iPhone 11", category: "phone"), Shop(name: "iPhone XR", category: "phone"), Shop(name: "Redmi note8", category: "phone"), Shop(name: "卫龙", category: "food"), Shop(name: "老干妈", category: "food")] let allCategory = Set(shops.map { $0.category }) var shopSections = [String: [Shop]]() allCategory.forEach { (cate) in let cateShops = shops.filter { $0.category == cate } shopSections[cate] = cateShops } 复制代码
在 Swift 5.0 发布以后,Dictionary 新添加了一个初始化方法:init(grouping:by:)
。该方法可以通过闭包中返回的 key 将数组组织为一个字典。用该方法重写上面的代码:
let shopSections = Dictionary(grouping: shops) { (shop) -> String in return shop.category } 复制代码
上面的代码可以通过 Swift 的语法糖更加精简:
let shopSections = Dictionary(grouping: shops) { $0.category } 复制代码
因为该方法提供了一个闭包来给我们操作,所以我们不仅仅可以返回当前模型的字段,我们还可以根据需求来灵活变通。比如上面的例子中,假如我们的需求变更为按商品的归属地来进行分类。虽然后台返回的字段没有返回,但我们依然可以通过商品来进行判断:
let shopSections = Dictionary(grouping: shops) { (shop) -> String in if shop.name.contains("iPhone") { return "US" } return "China" } print(shopSections) /* ["US": [DataStructureDemo.Shop(name: "iPhone 11", category: "phone"), DataStructureDemo.Shop(name: "iPhone XR", category: "phone")], "China": [DataStructureDemo.Shop(name: "Redmi note8", category: "phone"), DataStructureDemo.Shop(name: "卫龙", category: "food"), DataStructureDemo.Shop(name: "薯条", category: "food")]] */ 复制代码
大家都知道只要遵守 Hashable 的数据类型都可以当做字典的 key,比如 Int、String等。所以,我们也可以让结构体来当做字典的 key,只要它遵守了该协议:
struct Company: Hashable { let name: String } struct Shop { let name: String let category: String let company: Company } let apple = Company(name: "苹果") let littleMi = Company(name: "小米") let wl = Company(name: "卫龙") let lgm = Company(name: "老干妈") let shops = [Shop(name: "iPhone 11", category: "phone", company: apple), Shop(name: "iPhone XR", category: "phone", company: apple), Shop(name: "Redmi note8", category: "phone", company: littleMi), Shop(name: "卫龙", category: "food", company: wl), Shop(name: "薯条", category: "food", company: lgm)] let shopSections = Dictionary(grouping: shops) { return $0.company } print(shopSections) /* [DataStructureDemo.Company(name: "小米"): [DataStructureDemo.Shop(name: "Redmi note8", category: "phone", company: DataStructureDemo.Company(name: "小米"))], DataStructureDemo.Company(name: "苹果"): [DataStructureDemo.Shop(name: "iPhone 11", category: "phone", company: DataStructureDemo.Company(name: "苹果")), DataStructureDemo.Shop(name: "iPhone XR", category: "phone", company: DataStructureDemo.Company(name: "苹果"))], DataStructureDemo.Company(name: "卫龙"): [DataStructureDemo.Shop(name: "卫龙", category: "food", company: DataStructureDemo.Company(name: "卫龙"))], DataStructureDemo.Company(name: "老干妈"): [DataStructureDemo.Shop(name: "薯条", category: "food", company: DataStructureDemo.Company(name: "老干妈"))]] */ 复制代码
希望本文能让你清晰的知道该如何使用 init(grouping:by:)
,能给你带来更高的开发效率。😄