提问者:小点点

Swift sorted(by:)方法无法根据整数正确排序结构数组


我需要对一些自定义结构对象的数组进行排序。我的结构包含一个“user _ id”Int值,我必须用它来对数组进行排序。到目前为止,没有什么真正令人兴奋的。

然后,我必须强制一个项目(基于它的user_id)保持在我的列表的顶部,即。作为我的排序数组的第一个元素。

我带来了当前代码:

myArray.sorted(by: { $0.user_id == 40 ? true : $0.user_id < $1.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: { $0.user_id == 40 ? true : $0.user_id < $1.user_id })
    }

    var body: some View {
    VStack {
        ForEach(displayedMembers) { member in
            ...
        }
        .onAppear(perform: fetchMembers)
    }

我可以保证问题出在< code>displayedMembers变量中,因为我还尝试在我的主体中使用以下代码来调试它:< code > Text((displayed members . map { $ 0 . user _ id . description })。已连接(分隔符:" "))

知道我的比较有什么问题吗?谢谢你的帮助!


共1个答案

匿名用户

Array.sorted(by:)的谓词要求您

如果其第一个参数应在其第二个参数之前排序,则返回true;否则为假。

传递给谓词的参数的顺序可以按顺序((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 $0 and $1
    // have the same `user_id`, we need to return `false`. Checking $1.user_id
    // first hits two birds with one stone.
    if $1.user_id == 40 {
        return false
    } else if $0.user_id == 40 {
        return true
    }
    
    return $0.user_id < $1.user_id
})

然后你会得到一致的结果。

或者,如果提前知道该元素,则可以通过将其从列表中提取并对其余结果进行排序来避免这种情况。