Как отсортировать в swift по BOOL без изменения исходного порядка в основном массиве? - PullRequest
2 голосов
/ 03 апреля 2019

У меня есть один массив моделей, который имеет 2 свойства:

1.Заголовок (Строка)

2.selected (Bool)

Я хочу отсортировать их на основе свойства selected так, чтобы оно относилось к последовательности исходного массива.Например, если все имеют значение FALSE или TRUE, то после упорядочения должны быть одинаковые выходные данные.

Но если я использую следующее, после упорядочения они изменяют исходную сортировку на основе этого свойства BOOL.

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

Что я должен сделать, чтобы сохранить исходную последовательность?

РЕДАКТИРОВАТЬ 1:

Порядок сортировки Title не отображается.Может быть сервер отправит мне 4 объекта с названиями Z, Y, P, A.Так что, если все ложно, и как только я сортирую, это должно быть как Z ложь, Y ложь, P ложь, ложь.

Ответы [ 4 ]

3 голосов
/ 03 апреля 2019

Вам нужно

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 голос
/ 03 апреля 2019

Вместо сортировки вы можете сделать это более эффективно, используя операцию фильтра:

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
}
1 голос
/ 03 апреля 2019

Если вы хотите сохранить порядок, полученный с сервера, я предлагаю вам не использовать метод sort или sorted, поскольку они не гарантируют сохранение исходного порядка для ключей с таким же порядком.Я рекомендую вам написать собственную сортирующую функцию:

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)
 ]
1 голос
/ 03 апреля 2019

Вы должны использовать метод sorted вместо sort;

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

В основном sort сортирует в том же массиве, sorted возвращает новый массив без изменения исходного

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...