如何在不更改主数组原始顺序的情况下通过BOOL快速排序?

时间:2019-04-03 11:58:26

标签: ios arrays swift sorting nsarray

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

1。标题(字符串)

2。已选择(布尔)

我想基于selected属性对它们进行排序,以使其相对于源数组的顺序起作用。例如,如果全部为FALSE或TRUE,则订购后应该有相同的输出。

但是,如果我使用following,它会根据该BOOL属性对原始排序进行排序后更改原始排序。

someArray = array.sort { $0.selected && !$1.selected }

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

  

编辑1:

Title的排序顺序没有出现。可能是服务器向我发送了标题为Z,Y,P,A的4个对象。因此,如果全部为假,并且一旦我进行排序,就应该像Z假,Y假,P假,A假。

4 个答案:

答案 0 :(得分:3)

您需要

someArray = array.sorted (by:{ $0.selected && !$1.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

答案 1 :(得分:1)

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

let newArray = array.sorted { $0.selected && !$1.selected }

基本上sort在同一数组中排序,sorted返回一个新数组,而不更改原始数组

答案 2 :(得分:1)

如果要保留从服务器获得的顺序,我建议您不要使用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)
 ]

答案 3 :(得分:1)

代替排序,您可以使用过滤器操作更有效地做到这一点:

let newArray = array.filter { $0.selected } + array.filter { !$0.selected }

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

尽管如此,您仍可以轻松实现稳定的排序(例如https://stackoverflow.com/a/50545761/669586

然后您可以简单地使用:

let newArray = array.stableSorted {    
   let numeric1 = $0.selected ? 0 : 1
   let numeric2 = $1.selected ? 0 : 1

   return numeric1 <= numeric2
}

let newArray = array.stableSorted {
   return $0.selected == $1.selected || $0.selected
}