简体   繁体   English

使用sortedArrayUsingComparator对NSArray进行排序

[英]Sort NSArray with sortedArrayUsingComparator

In Objective-C I can sort an NSArray using this statement: Objective-C我可以使用以下语句对NSArray进行排序:

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

I'm unable to reproduce the same statement with Swift . 我无法用Swift重现相同的声明。 All I found was using Array . 我发现的只是使用Array

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. 您可以使用Swift的内置排序函数,或者由于Swift数组桥接到NSArray您可以直接从swift调用sortedArrayUsingComparator

Using Swift's sorted function: 使用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
}

Or, using NSArray 's sortedArrayUsingComparator : 或者,使用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
}

There's no need to avoid Swift Array . 没有必要避免使用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. 它使用NSArray在两个方向上进行桥接,因此对于更安全类型的代码,最好只在需要与ObjC API进行互操作时使用Swift数组和桥接。 (And in most imported APIs, Swift automatically converts NSArray to [AnyObject] , so you don't even need to bridge very often.) (在大多数导入的API中,Swift会自动将NSArray转换为[AnyObject] ,因此您甚至不需要经常桥接。)

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: 假设persons数组是从其他API获得的[AnyObject] ,您可以通过首先强制转换数组来减少类型转换相对于其他答案的数量:

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: 此外,由于您仅使用比较器块对Person类的特定属性进行排序,因此最好使用排序描述符:

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.) (如果persons来自ObjC API,则可能不需要persons as NSArray部分persons 。)

Depending on how the Person class is implemented, sorting with descriptors can produce a more efficient sort on the backend. 根据Person类的实现方式,使用描述符进行排序可以在后端生成更高效的排序。 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. 例如,如果它是一个核心数据管理对象,使用描述符进行排序可能会产生一个SQL查询,该查询在数据库中执行速度很快并且使用很少的内存,而使用比较器闭包进行排序则需要从数据库中实例化每个对象,只是为了评估每个对象的关闭。 。

So try just write the same with Swift: 所以试着用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")

In Swift you can use new approach. 在Swift中,您可以使用新方法。 Try to use sorted method instead sortedArrayUsingComparator like this... 尝试使用sorted方法而不是sortedArrayUsingComparator这样...

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

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
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM