如何在不更改主数组中原始顺序的情况下按 BOOL 对 swift 进行排序?

How to sort in swift by a BOOL without changing the original order in main array?

我有一组具有 2 个属性的模型:

1.标题(字符串)

2。 isSelected (布尔)

我想根据 isSelected 属性 对它们进行排序,使其相对于源数组的顺序进行排序。例如,如果全部为 FALSE 或 TRUE,则在排序后应该有相同的输出。

但是,如果我使用以下方法,它会在根据该 BOOL 属性.

对它们进行排序后改变原始排序
someArray = array.sort { [=11=].selected && !.selected }

我应该怎么做才能保留原始序列?

EDIT 1

title 的排序顺序不在图片中。可能是服务器向我发送了 4 objects,标题为 Z、Y、P、A。所以如果所有都是假的,一旦我排序,它应该像 Z false,Y false, P false, A false.

你需要

someArray = array.sorted (by:{ [=10=].selected && !.selected && <#Add more conditions #>})

sorted (by 不像 sort

那样改变原始数组

https://developer.apple.com/documentation/swift/array/1688499-sort

https://developer.apple.com/documentation/swift/array/2296815-sorted

您应该使用 sorted 方法而不是 sort;

let newArray = array.sorted { [=10=].selected && !.selected }

基本上sort在同一个数组中排序,sortedreturn一个新的数组,不改变原来的

如果你想保留从服务器获得的顺序,我建议你不要使用 sortsorted 方法,因为它们不能保证保留密钥的原始顺序同样的顺序。我会建议您编写自己的类似排序的函数:

struct Model {
    let title:String
    let selected:Bool
}

let array = [ Model(title: "Z", selected: true), Model(title: "Z", selected: false), Model(title: "Y", selected: false), Model(title: "P", selected: false), Model(title: "A", selected: true), Model(title: "A", selected: false)]

extension Array where Element == Model {
    func preserveSorted() -> [Model] {
        var selected:[Model] = []
        var notSelected:[Model] = []

        for model in self {
            if model.selected {
                selected.append(model)
            } else {
                notSelected.append(model)
            }
        }
        var output:[Model] = []
        output.append(contentsOf: selected)
        output.append(contentsOf: notSelected)
        return output
    }
}


var newArray:[Model] = array.preserveSorted()
print(newArray)
/* output:
[
    Model(title: "Z", selected: true),
    Model(title: "A", selected: true),
    Model(title: "Z", selected: false),
    Model(title: "Y", selected: false),
    Model(title: "P", selected: false),
    Model(title: "A", selected: false)
]
*/

如果您不想为您的模型创建 Comparable 扩展(例如,因为您在一些地方使用了不同顺序的这些模型),您可以使用方法 sorted,但提供不同的排序块:

struct Model {
    let title:String
    let selected:Bool
}

let array = [ Model(title: "a", selected: true), Model(title: "a", selected: false), Model(title: "b", selected: false), Model(title: "c", selected: true)]

let newArray = array.sorted { (lhs, rhs) -> Bool in
    if lhs.selected == rhs.selected {
        return lhs.title < rhs.title
    }
    return lhs.selected
}
print(newArray)

排序顺序为:

[
  Model(title: "a", selected: true), 
  Model(title: "c", selected: true), 
  Model(title: "a", selected: false), 
  Model(title: "b", selected: false)
 ]

您可以使用过滤操作更有效地代替排序:

let newArray = array.filter { [=10=].selected } + array.filter { ![=10=].selected }

不幸的是,Array.sorted 不能保证排序稳定,因此您不能仅按一个 属性 排序并期望保留原始排序。

不过您可以轻松实现稳定排序(例如

那么你可以简单地使用:

let newArray = array.stableSorted {    
   let numeric1 = [=11=].selected ? 0 : 1
   let numeric2 = .selected ? 0 : 1

   return numeric1 <= numeric2
}

let newArray = array.stableSorted {
   return [=12=].selected == .selected || [=12=].selected
}