我有一个动态的属性数组,例如:
var compareAttributes = ["name", "is_active", "age"]
可以随时更改项目及其计数。
我需要根据此列表中的所有属性(按顺序)对数组进行排序,所有这些属性都是ACCEDING。
我使用NSSortDiscrptors
尝试了OBJ-C方式但是由于我的数组包含[JSON]
个对象,我无法将其转换为NSArray:
class func sortServerObjectsByCompareAttributes( responseObjects: [JSON]) {
var sortDiscriptors = [NSSortDescriptor]()
for attribute in compareAttributes {
sortDiscriptors.append(NSSortDescriptor(key: attribute, ascending: true))
}
let sortedByAge = (responseObjects as NSArray).sortedArrayUsingDescriptors(sortDiscriptors) // error is [JSON] is not convertible to NSArray
}
我知道如何使用1个属性对其进行排序:
responseObjects.sortInPlace({$0[compareAttribute] < $1[compareAttribute]})
我需要的是这样的方法:
fun sortArray(responseObjects: [JSON], sortProperties: [string]) {
//perform the sort
}
我怎样才能迅速实现这一目标?
由于
答案 0 :(得分:1)
我不知道你想走多远。找到一个Swifty方法来做到这一点并不容易,因为Swift有严格的输入和没有内省。在Objective-C中实现自己的排序描述符方法的一切都很难在Swift中完成。 NSSortDescriptor依赖于键值编码,这正是JSON对象中缺少的原因,因为它是一个Swift结构。你需要的是一个NSObject衍生物。如果您使用内置的NSJSONSerialization,那就是您现在拥有的,其余的将很容易。但是当你使用SwiftJSON时,你就抛弃了这个功能。
然而,仅作为如何通过&#34;键&#34;进行分类的示例在特殊情况下,让我们想象一下这样的事情:
protocol StringSubscriptable {
subscript(which:String) -> String {get}
}
struct Thing : StringSubscriptable {
var p1 : String
var p2 : String
var p3 : String
subscript(which:String) -> String {
switch which {
case "p1": return p1
case "p2": return p2
case "p3": return p3
default: return ""
}
}
}
你看到我在这里建造了什么?它是一个纯粹的Swift结构,Thing,它具有我手动键值可编码的属性,通过提供一个subscript
方法来获取每个结构的String值。属性基于属性的字符串名称。
StringSubscriptable协议只是一种基于协议的方式来保证Thing具备这种能力。
鉴于这一切,我们可以扩展Array来做你想要的:
extension Array where Element : StringSubscriptable {
mutating func sortByList(list:[String]) {
func sortHelper(a:StringSubscriptable, _ b:StringSubscriptable, _ ix:Int) -> Bool {
let key = list[ix]
if a[key] == b[key] && ix < list.count - 1 {
return sortHelper(a, b, ix + 1)
}
return a[key] < b[key]
}
self.sortInPlace { sortHelper($0, $1, 0) }
}
}
这个想法是你递给sortByList
一个键列表,我们按顺序基于这些键对Thing数组(因为它是一个StringSubscriptable)进行排序。对于每一对,如果第一个键足以确定结果,我们对它进行排序,但如果第一个键给出了该对的相同结果,我们使用第二个键(这就是子搜索的内容)。
举例说明:
let t1 = Thing(p1: "y", p2: "ho", p3: "x")
let t2 = Thing(p1: "z", p2: "ho", p3: "x")
let t3 = Thing(p1: "z", p2: "ho", p3: "a")
var arr = [t1,t2,t3]
arr.sortByList(["p3", "p2", "p1"])
结果是
[
Thing(p1: "z", p2: "ho", p3: "a"),
Thing(p1: "y", p2: "ho", p3: "x"),
Thing(p1: "z", p2: "ho", p3: "x")
]
如果你仔细想想,那就是正确的答案。首先,我们对&#34; p3&#34;进行排序,因此p3
值为"a"
的Thing排在第一位。但对于其他两个,他们的p3
值是相同的,所以我们回到他们的p3
值。它们也是一样的,所以我们会回到p1
的{{1}}值,"y"
在"z"
之前。