根据对应于特定属性的另一个数组中的值对对象数组sorting

比方说从JSON API中检索一个对象数组:

[ { "id": 48, "name": "Bob" }, { "id": 198, "name": "Dave" }, { "id": 2301, "name": "Amy" }, { "id": 990, "name": "Colette" } ] // eg 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] 

如何根据sorting索引中的ID顺序重新sorting原始数据对象数组?

 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)将数据parsing成简单的字典,其中字典的关键字是用于对其进行sorting的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)用一些自定义的DataObjecttypes:(可能是最好的方法)

 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所具有的function支持,并使用map函数迭代index数组并获取相应的对象:

 let sortedObjects = index.map{ id in dataObjects.filter{ $0["id"] as? Int == id }.first } 

这假定在映射数据对象之前, index数组是正确计算的。


编辑

感谢user3441734的flatMapbuild议。 这里有一个解决scheme,它使用它,基本上它简单地用flatMapreplacemap ,以便摆脱映射数组中可能的nil值,并将结果数组转换为非可选项的数组。

 let sortedObjects = index.flatMap{ id in dataObjects.filter{ $0["id"] as? Int == id }.first } 

如果一个空的index应该保持相同的顺序,那么我们可以简单地testing一下:

 let sortedObjects = index.count > 0 ? index.flatMap{ id in dataObjects.filter{ $0["id"] as? Int == id }.first } : dataObjects 

你不需要保持一个数组的索引,你可以通过你想要的对象进行sorting,让我们说你有以下结构:

 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函数对结果进行sorting并将结果返回给其他数组,或者如果你想使它到位

 // ordered by id var sortedData = data.sort { index.indexOf($0.id) < index.indexOf($1.id) } 

我希望这可以帮助你。