Подтвердить что ты не робот

Сортировка NSArray с sortedArrayUsingComparator

В Objective-C я могу сортировать NSArray с помощью этого оператора:

NSArray *sortedArray = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *p1, Person *p2) {
    return [p1.name compare:p2.name];
}];

Я не могу воспроизвести тот же оператор с Swift. Все, что я нашел, это использовать Array.

4b9b3361

Ответ 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
        }