gpt4 book ai didi

swift - 根据动态属性列表对 Swift Array 进行排序

转载 作者:行者123 更新时间:2023-11-30 10:11:07 25 4
gpt4 key购买 nike

我有一个动态属性数组,例如:

var compareAttributes = ["name", "is_active", "age"]

项目及其数量始终可以更改。

我需要根据此列表中的所有属性(按顺序)对数组进行排序,所有属性均已接受。

我尝试使用 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
}

如何快速实现这一目标?

谢谢

最佳答案

我不确定你想在这方面走多远。找到一种 Swifty 的方法来做到这一点并不容易,因为 Swift 有严格的类型并且没有内省(introspection)。在 Objective-C 中实现自己的按排序描述符排序方法的所有事情在 Swift 中都很难做到。 NSSortDescriptor 依赖于键值编码,这正是 JSON 对象所缺少的,因为它是 Swift 结构。这里你需要的是一个 NSObject 衍生品。如果您继续使用内置的 NSJSONSerialization,这就是您现在所拥有的,其余的就很容易了。但当您使用 SwiftJSON 时,您就抛弃了该功能。

但是,作为在特殊情况下如何按“key”进行子排序的示例,让我们想象一下这样的事情:

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 协议(protocol)只是一种基于协议(protocol)的方式来保证 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")
]

如果你仔细想想,这就是正确的答案。首先,我们对“p3”进行排序,因此具有 p3“a” 的事物排在第一位。但对于其他两个,它们的 p3 值是相同的,因此我们依靠它们的 p3 值。它们也相同,因此我们依靠它们的 p1 值,并且 "y" 位于 "z" 之前。

关于swift - 根据动态属性列表对 Swift Array 进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33022995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com