假设从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"]
]
/*
答案 0 :(得分:2)
方法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)
答案 1 :(得分:2)
您可以从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
答案 2 :(得分:1)
您不需要使用您可以按所需对象排序的索引来保留数组,让我们说您具有以下结构:
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) }
我希望这对你有所帮助。