Sort NSArray with sortedArrayUsingComparator

后端 未结 5 572
生来不讨喜
生来不讨喜 2020-12-14 01:36

In Objective-C I can sort an NSArray using this statement:

NSArray *sortedArray = [persons sortedArrayUsingComparator:^NSComparison         


        
相关标签:
5条回答
  • 2020-12-14 02:01

    in case you have custom object and want to sort by date

    let sortedArray = self.posts.sorted {
                (obj1, obj2) -> Bool in
                return (obj1 as! PostModel).orderCancellionDate.compare( (obj2 as! PostModel).orderCancellionDate) == .orderedDescending
            }
    
    0 讨论(0)
  • 2020-12-14 02:03

    In Swift you can use new approach. Try to use sorted method instead sortedArrayUsingComparator like this...

    var sortedArray = results.sorted {
        (obj1, obj2) -> Bool in 
        return obj1.count! > obj2.count!
    }
    
    0 讨论(0)
  • 2020-12-14 02:06

    You can either use Swift's built in sort functions or, since a Swift array is bridged to NSArray you can call sortedArrayUsingComparator from swift directly.

    Using Swift's sorted function:

    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
    }
    

    Or, using NSArray's 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
    }
    
    0 讨论(0)
  • 2020-12-14 02:13

    So try just write the same with 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
     }
    

    Test (Playground):

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

    Output:

    Optional("a")
    Optional("b")
    Optional("c")
    
    0 讨论(0)
  • 2020-12-14 02:21

    There's no need to avoid Swift Array.

    It's bridged in both directions with NSArray, so for more type-safe code it's best to do your work with Swift arrays and bridge only when needed for interoperating with ObjC APIs. (And in most imported APIs, Swift automatically converts NSArray to [AnyObject], so you don't even need to bridge very often.)

    Assuming the persons array is an [AnyObject] you got from other API, you can cut down on the amount of type casting relative to other answers by casting the array first:

    let sortedPersons = sorted(persons as [Person]) { $0.name < $1.name }
    // sortedPersons has inferred type [Person]
    

    Also, since you're using a comparator block only to sort on a specific property of your Person class, you might do better to use sort descriptors:

    let sortedPersons = (persons as NSArray).sortedArrayUsingDescriptors([
        NSSortDescriptor(key: "name", ascending: true)
    ])
    

    (The persons as NSArray part may not be necessary if persons came from an ObjC API.)

    Depending on how the Person class is implemented, sorting with descriptors can produce a more efficient sort on the backend. For example, if it's a Core Data managed object, sorting with descriptors might produce a SQL query that executes fast in the database and uses little memory, while sorting with a comparator closure requires instantiating every object from the database just to evaluate the closure against each.

    0 讨论(0)
提交回复
热议问题