web-dev-qa-db-ja.com

sortArrayUsingComparatorでNSArrayをソートする

Objective-C次のステートメントを使用してNSArrayをソートできます。

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

Swiftで同じステートメントを再現することはできません。私が見つけたのは、Arrayを使用することだけでした。

24
Paulo Rodrigues

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
}

または、NSArraysortedArrayUsingComparatorを使用します。

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
}
36
Mike S

回避する必要はありませんSwift Array

NSArrayで双方向にブリッジされているため、よりタイプセーフなコードの場合は、Swift配列で作業し、ObjC APIとの相互運用に必要な場合にのみブリッジするのが最善です。また、ほとんどのインポートされたAPIでは、SwiftはNSArray[AnyObject]に自動的に変換するため、頻繁にブリッジする必要さえありません。)

persons配列が他のAPIから取得した[AnyObject]であると仮定すると、最初に配列をキャストすることにより、他の回答と比較して型キャストの量を削減できます。

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)
])

personsがObjC APIからのものである場合、persons as NSArray部分は不要な場合があります。)

Personクラスの実装方法に応じて、記述子を使用したソートは、バックエンドでより効率的なソートを生成できます。たとえば、コアデータ管理オブジェクトの場合、記述子を使用した並べ替えでは、データベースで高速に実行され、メモリをほとんど使用しないSQLクエリが生成されますが、コンパレータクロージャーを使用した並べ替えでは、それぞれに対してクロージャーを評価するためにデータベースからすべてのオブジェクトをインスタンス化する必要があります。

14
rickster

だから、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")
9
Maxim Shoustin

Swift新しいアプローチを使用できます。このようにsortedArrayUsingComparatorの代わりにsortedメソッドを使用してみてください...

var sortedArray = results.sorted {
    (obj1, obj2) -> Bool in 
    return obj1.count! > obj2.count!
}
0
d0ping

カスタムオブジェクトがあり、日付でソートしたい場合

let sortedArray = self.posts.sorted {
            (obj1, obj2) -> Bool in
            return (obj1 as! PostModel).orderCancellionDate.compare( (obj2 as! PostModel).orderCancellionDate) == .orderedDescending
        }
0
Spydy