Swift sorted(by:) 方法无法根据整数正确排序结构数组
Swift sorted(by:) method doesn't correctly sort an array of struct based on integer
我需要对一些自定义结构对象的数组进行排序。我的结构包含一个“user_id”Int 值,这是我必须用来对数组进行排序的值。到目前为止,没有什么真正令人兴奋的。
然后我必须强制一项(基于其 user_id)保留在我的列表顶部,即。作为排序数组的第一个元素。
我是用当前代码来的:
myArray.sorted(by: { [=11=].user_id == 40 ? true : [=11=].user_id < .user_id })
但有时(并非总是)数组似乎完全忽略了第一次比较,只是根据 user_id 对项目进行排序。因此,例如,如果我的列表包含元素 37、40、41,它将被排序为 [40、37、41] 或 [37、40、41],但我找不到原因或方式。
对于上下文:我在 SwiftUI 视图中的动态变量(我忘记了它们是如何调用的)中使用此列表,它使用 ForEach(mySortedArray) 构建已排序自定义行的 VStack。所以基本上 SwiftUI 代码看起来像那样(BoardMember 是我的自定义结构):
@State private var boardPerms: [BoardMember] = []
func fetchMembers() {
boardPerms = ...
}
var displayedMembers: [BoardMember] {
boardPerms.sorted(by: { [=12=].user_id == 40 ? true : [=12=].user_id < .user_id })
}
var body: some View {
VStack {
ForEach(displayedMembers) { member in
...
}
.onAppear(perform: fetchMembers)
}
我可以确定问题出在 displayedMembers
var 中,因为我还尝试使用我体内的以下代码对其进行调试:Text((displayedMembers.map{[=14=].user_id.description}).joined(separator: " "))
知道我的比较有什么问题吗?感谢您的帮助!
Array.sorted(by:) 的谓词要求您
return true if its first argument should be ordered before its second argument; otherwise, false.
传递给谓词的参数的顺序可以按任意顺序给出((a, b)
或 (b, a)
),具体取决于列表的排列方式到目前为止已排序,但谓词 必须 以任一顺序给出一致的结果,否则你将得到无意义的结果。
在您的谓词中,您正在检查 第一个 元素的用户 ID 以确定它的优先级,但 不是 第二个;即,您正在处理 (a, b)
但 而不是 (b, a)
。如果您将谓词更新为
myArray.sorted(by: {
// The order of the checking here matters. Specifically, the predicate
// requires a `<` relationship, not a `<=` relationship. If both [=10=] and
// have the same `user_id`, we need to return `false`. Checking .user_id
// first hits two birds with one stone.
if .user_id == 40 {
return false
} else if [=10=].user_id == 40 {
return true
}
return [=10=].user_id < .user_id
})
然后你会得到一致的结果。
或者,如果元素提前已知,您可以通过从列表中提取它并对剩余结果进行排序来避免这种情况。
我需要对一些自定义结构对象的数组进行排序。我的结构包含一个“user_id”Int 值,这是我必须用来对数组进行排序的值。到目前为止,没有什么真正令人兴奋的。
然后我必须强制一项(基于其 user_id)保留在我的列表顶部,即。作为排序数组的第一个元素。
我是用当前代码来的:
myArray.sorted(by: { [=11=].user_id == 40 ? true : [=11=].user_id < .user_id })
但有时(并非总是)数组似乎完全忽略了第一次比较,只是根据 user_id 对项目进行排序。因此,例如,如果我的列表包含元素 37、40、41,它将被排序为 [40、37、41] 或 [37、40、41],但我找不到原因或方式。
对于上下文:我在 SwiftUI 视图中的动态变量(我忘记了它们是如何调用的)中使用此列表,它使用 ForEach(mySortedArray) 构建已排序自定义行的 VStack。所以基本上 SwiftUI 代码看起来像那样(BoardMember 是我的自定义结构):
@State private var boardPerms: [BoardMember] = []
func fetchMembers() {
boardPerms = ...
}
var displayedMembers: [BoardMember] {
boardPerms.sorted(by: { [=12=].user_id == 40 ? true : [=12=].user_id < .user_id })
}
var body: some View {
VStack {
ForEach(displayedMembers) { member in
...
}
.onAppear(perform: fetchMembers)
}
我可以确定问题出在 displayedMembers
var 中,因为我还尝试使用我体内的以下代码对其进行调试:Text((displayedMembers.map{[=14=].user_id.description}).joined(separator: " "))
知道我的比较有什么问题吗?感谢您的帮助!
Array.sorted(by:) 的谓词要求您
return true if its first argument should be ordered before its second argument; otherwise, false.
传递给谓词的参数的顺序可以按任意顺序给出((a, b)
或 (b, a)
),具体取决于列表的排列方式到目前为止已排序,但谓词 必须 以任一顺序给出一致的结果,否则你将得到无意义的结果。
在您的谓词中,您正在检查 第一个 元素的用户 ID 以确定它的优先级,但 不是 第二个;即,您正在处理 (a, b)
但 而不是 (b, a)
。如果您将谓词更新为
myArray.sorted(by: {
// The order of the checking here matters. Specifically, the predicate
// requires a `<` relationship, not a `<=` relationship. If both [=10=] and
// have the same `user_id`, we need to return `false`. Checking .user_id
// first hits two birds with one stone.
if .user_id == 40 {
return false
} else if [=10=].user_id == 40 {
return true
}
return [=10=].user_id < .user_id
})
然后你会得到一致的结果。
或者,如果元素提前已知,您可以通过从列表中提取它并对剩余结果进行排序来避免这种情况。