before
Suppose we are developing an item page and the requirement is to section the item, but the data returned to us in the background is an array of items for the entire list. Before Swift 5, we could only group by iterating through groups:
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: "WeiLong", category: "food"),
Shop(name: Lao Gan Ma, 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
}
Copy the code
now
With Swift 5.0, Dictionary has a new initialization method: init(Grouping :by:). This method organizes the array into a dictionary using the key returned in the closure. Rewrite the above code with this method:
let shopSections = Dictionary(grouping: shops) { (shop) -> String in
return shop.category
}
Copy the code
The code above can be made more concise by Swift’s syntax:
let shopSections = Dictionary(grouping: shops) { $0.category }
Copy the code
More and more
Because this method provides a closure for us to operate on, we can not only return the fields of the current model, but we can also be flexible as needed. For example, in the example above, let’s say our requirements change to categorizing goods by where they belong. Although the field returned in the background does not return, we can still judge by the goods:
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: "WeiLong", category: "food"),
DataStructureDemo.Shop(name: "French fries", category: "food"* /)]]Copy the code
explore
We all know that you can use dictionary keys as long as you follow Hashable data types, such as Int, String, etc. So, we can also use a structure as a dictionary key, as long as it complies with the protocol:
struct Company: Hashable {
let name: String
}
struct Shop {
let name: String
let category: String
let company: Company
}
let apple = Company(name: The word "apple")
let littleMi = Company(name: "Millet")
let wl = Company(name: "WeiLong")
let lgm = Company(name: Lao Gan Ma)
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: "WeiLong", category: "food", company: wl),
Shop(name: "French fries", category: "food", company: lgm)]
let shopSections = Dictionary(grouping: shops) { return $0.company }
print(shopSections)
/*
[DataStructureDemo.Company(name: "Millet"): [DataStructureDemo.Shop(name: "Redmi note8", category: "phone", company: DataStructureDemo.Company(name: "Millet"))], DataStructureDemo.Company(name: The word "apple"): [DataStructureDemo.Shop(name: "iPhone 11", category: "phone", company: DataStructureDemo.Company(name: The word "apple")), DataStructureDemo.Shop(name: "iPhone XR", category: "phone", company: DataStructureDemo.Company(name: The word "apple"))], DataStructureDemo.Company(name: "WeiLong"): [DataStructureDemo.Shop(name: "WeiLong", category: "food", company: DataStructureDemo.Company(name: "WeiLong"))], DataStructureDemo.Company(name: Lao Gan Ma): [DataStructureDemo.Shop(name: "French fries", category: "food", company: DataStructureDemo.Company(name: Lao Gan Ma* /))]]Copy the code
Hopefully this article gives you a good idea of how to use Init (Grouping :by:) to be more efficient. 😄