[英]How to sort by increasing order an array of objects based on its properties - Swift
[英]Sort array of objects based on values in another array that correspond to specific properties
假設從JSON API檢索對象數組:
[
{
"id": 48,
"name": "Bob"
},
{
"id": 198,
"name": "Dave"
},
{
"id": 2301,
"name": "Amy"
},
{
"id": 990,
"name": "Colette"
}
]
// e.g. for ease of reproduction:
let dataObjects = [
["id": 48, "name": "Bob"],
["id": 198, "name": "Dave"],
["id": 2301, "name": "Amy"],
["id": 990, "name": "Colette"]
]
在客戶端上,我想允許用戶重新排序這些對象。 為了保存訂單,我將ID列表存儲在數組中:
let index: [Int] = [48, 990, 2103, 198]
如何根據排序索引中ID的順序對數據對象的原始數組重新排序?
dataObjects.sort({
// magic happens here maybe?
}
最終,我得到:
print(dataObjects)
/*
[
["id": 48, "name": "Bob"],
["id": 990, "name": "Colette"],
["id": 2301, "name": "Amy"],
["id": 198, "name": "Dave"]
]
/*
方法A)將數據解析為簡單的字典,其中字典的鍵是用於對其進行排序的ID:
func sort<Value>(a: [Int: Value], basedOn b: [Int]) -> [(Int, Value)] {
return a.sort { x, y in
b.indexOf(x.0) < b.indexOf(y.0)
}
}
// ....
let a = [48:"Bob", 198:"Dave", 2301:"Amy", 990:"Colette"]
let b = [48, 198, 2301, 990]
sort(a, basedOn: b)
方法B)使用一些自定義DataObject
類型:(可能是最好的方法)
struct DataObject {
let id: Int
let name: String
init(_ id: Int, _ name: String) {
self.id = id
self.name = name
}
}
func sort(a: [DataObject], basedOn b: [Int]) -> [DataObject] {
return a.sort { x, y in
b.indexOf(x.id) < b.indexOf(y.id)
}
}
let a = [DataObject(48, "Bob"), DataObject(198, "Dave"), DataObject(2301, "Amy"), DataObject(990, "Colette")]
let b = [48, 198, 2301, 990]
sort(a, basedOn: b)
/* [
DataObject(id: 48, name: "Bob"),
DataObject(id: 990, name: "Colette"),
DataObject(id: 198, name: "Dave"),
DataObject(id: 2301, name: "Amy")
] */
方法C)使用原始的 json值,可以用一種不太“干凈”的方式完成此操作:
func sort<Value>(a: [[String: Value]], basedOn b: [Int]) -> [[String: Value]] {
return a.sort { x, y in
let xId = x["id"] as! Int
let yId = y["id"] as! Int
return b.indexOf(xId) < b.indexOf(yId)
}
}
let dataObjects = [
["id": 48, "name": "Bob"],
["id": 198, "name": "Dave"],
["id": 2301, "name": "Amy"],
["id": 990, "name": "Colette"]
]
let b = [48, 198, 2301, 990]
sort(dataObjects, basedOn: b)
您可以受益於Swift的功能支持,並使用map
函數遍歷index
數組並獲取相應的對象:
let sortedObjects = index.map{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
}
這假定在映射數據對象之前已正確計算了index
數組。
感謝user3441734的flatMap
建議。 這里有一個解決方案,利用它,基本上它只是更換map
由flatMap
,以擺脫可能的nil
映射的數組中的值,以及所產生的數組轉換成非自選的數組。
let sortedObjects = index.flatMap{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
}
如果空index
應該導致保留相同的順序,那么我們可以簡單地測試一下:
let sortedObjects = index.count > 0 ? index.flatMap{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
} : dataObjects
您不需要保留帶有可以按所需對象排序的索引的數組,可以說您具有以下結構:
struct DataObject {
var id: Int
var name: String
}
var data = [DataObject]()
data.append(DataObject(id: 48, name: "Bob"))
data.append(DataObject(id: 198, name: "Dave"))
data.append(DataObject(id: 2301, name: "Amy"))
data.append(DataObject(id: 990, name: "Colette"))
您可以使用sort
函數對結果進行排序並將其返回到其他數組中,或者如果要使其就位,則可以使用sorted
函數
// ordered by id
var sortedData = data.sort { index.indexOf($0.id) < index.indexOf($1.id) }
希望對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.