Сортировка NSArray с sortedArrayUsingComparator
В Objective-C
я могу сортировать NSArray
с помощью этого оператора:
NSArray *sortedArray = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *p1, Person *p2) {
return [p1.name compare:p2.name];
}];
Я не могу воспроизвести тот же оператор с Swift. Все, что я нашел, это использовать Array
.
Ответы
Ответ 1
Вы можете использовать Swift, встроенный в функции сортировки, или, поскольку массив Swift подключен к NSArray
, вы можете вызвать sortedArrayUsingComparator
из swift напрямую.
Использование функции Swift sorted
:
var sortedArray = sorted(persons) {
(obj1, obj2) in
// The downcast to Person is only needed if persons is an NSArray or a Swift Array of AnyObjects
let p1 = obj1 as Person
let p2 = obj2 as Person
return p1.name < p2.name
}
Или, используя NSArray
sortedArrayUsingComparator
:
var sortedArray = persons.sortedArrayUsingComparator {
(obj1, obj2) -> NSComparisonResult in
let p1 = obj1 as Person
let p2 = obj2 as Person
let result = p1.name.compare(p2.name)
return result
}
Ответ 2
Нет необходимости избегать Swift Array
.
Он соединяется в обоих направлениях с помощью NSArray
, поэтому для более безопасного типа кода лучше всего выполнять свою работу с массивами Swift и мостом только тогда, когда это необходимо для взаимодействия с API-интерфейсами ObjC. (И в большинстве импортированных API Swift автоматически преобразует NSArray
в [AnyObject]
, поэтому вам даже не нужно очень часто связываться.)
Предполагая, что массив persons
- это [AnyObject]
, который вы получили от другого API, вы можете сократить количество литья типов по сравнению с другими ответами, сначала запустив массив:
let sortedPersons = sorted(persons as [Person]) { $0.name < $1.name }
// sortedPersons has inferred type [Person]
Кроме того, поскольку вы используете блок компаратора только для сортировки по определенному свойству вашего класса Person
, вам лучше использовать дескрипторы сортировки:
let sortedPersons = (persons as NSArray).sortedArrayUsingDescriptors([
NSSortDescriptor(key: "name", ascending: true)
])
(<<29 > часть может не понадобиться, если persons
получен из API ObjC.)
В зависимости от того, как реализуется класс Person
, сортировка с дескрипторами может привести к более эффективному сортировке на сервере. Например, если это объект, управляемый основными данными, сортировка с дескрипторами может привести к выполнению SQL-запроса, который выполняется быстро в базе данных и использует небольшую память, а при сортировке с закрытием компаратора требуется создать экземпляр каждого объекта из базы данных только для оценки закрытия по каждому.
Ответ 3
Так что попробуйте просто написать то же самое с Swift:
var sortedArray:NSArray =
persons.sortedArrayUsingComparator(){(p1:AnyObject!, p2:AnyObject!) -> NSComparisonResult in
if (p1 as Person).name > (p2 as Person).name {
return NSComparisonResult.OrderedDescending
}
if (p1 as Person).name < (p2 as Person).name {
return NSComparisonResult.OrderedAscending
}
return NSComparisonResult.OrderedAscending
}
Тест (игровая площадка):
class Person{
var name:String?
}
var p1:Person = Person()
p1.name = "a"
var p3:Person = Person()
p3.name = "c"
var p2:Person = Person()
p2.name = "b"
var persons:NSArray = [p1,p3,p2]
var sortedArray:NSArray = persons.sortedArrayUsingComparator(){
(p1:AnyObject!, p2:AnyObject!) -> NSComparisonResult in
if (p1 as Person).name > (p2 as Person).name {
return NSComparisonResult.OrderedDescending
}
if (p1 as Person).name < (p2 as Person).name {
return NSComparisonResult.OrderedAscending
}
return NSComparisonResult.OrderedAscending
}
for item:AnyObject in sortedArray{
println((item as Person).name)
}
Вывод:
Optional("a")
Optional("b")
Optional("c")
Ответ 4
В Swift вы можете использовать новый подход. Попробуйте использовать отсортированный метод вместо sortedArrayUsingComparator, как это...
var sortedArray = results.sorted {
(obj1, obj2) -> Bool in
return obj1.count! > obj2.count!
}
Ответ 5
если у вас есть пользовательский объект и вы хотите сортировать по дате
let sortedArray = self.posts.sorted {
(obj1, obj2) -> Bool in
return (obj1 as! PostModel).orderCancellionDate.compare( (obj2 as! PostModel).orderCancellionDate) == .orderedDescending
}