Dans Objective-C
, je peux trier une NSArray
en utilisant cette déclaration:
NSArray *sortedArray = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *p1, Person *p2) {
return [p1.name compare:p2.name];
}];
Je suis incapable de reproduire la même déclaration avec Swift . Tout ce que j'ai trouvé utilisait Array
.
Vous pouvez utiliser les fonctions de tri intégrées de Swift ou, puisqu'un tableau Swift est ponté sur NSArray
, vous pouvez appeler sortedArrayUsingComparator
directement depuis Swift.
Utilisation de la fonction sorted
de Swift:
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
}
Ou, en utilisant 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
}
Il n'y a pas besoin d'éviter Swift Array
.
Il est ponté dans les deux sens avec NSArray
. Par conséquent, pour un code plus sûr en termes de types, il est préférable de travailler avec les baies et le tableau Swift uniquement lorsque cela est nécessaire pour l'interopérabilité avec les API ObjC. (Et dans la plupart des API importées, Swift convertit automatiquement NSArray
en [AnyObject]
, de sorte que vous n'avez même pas besoin de créer de passerelles très souvent.)
En supposant que le tableau persons
soit un [AnyObject]
que vous avez obtenu d'une autre API, vous pouvez réduire le nombre de transformations de types par rapport aux autres réponses en convertissant d'abord le tableau:
let sortedPersons = sorted(persons as [Person]) { $0.name < $1.name }
// sortedPersons has inferred type [Person]
De plus, comme vous utilisez un bloc de comparaison uniquement pour trier une propriété spécifique de votre classe Person
, vous feriez peut-être mieux d'utiliser des descripteurs de tri:
let sortedPersons = (persons as NSArray).sortedArrayUsingDescriptors([
NSSortDescriptor(key: "name", ascending: true)
])
(La partie persons as NSArray
peut ne pas être nécessaire si persons
provient d'une API ObjC.)
Selon la façon dont la classe Person
est implémentée, le tri avec des descripteurs peut produire un tri plus efficace sur le backend. Par exemple, s'il s'agit d'un objet géré Core Data, le tri avec des descripteurs peut générer une requête SQL rapide dans la base de données et utilisant peu de mémoire, tandis que le tri avec une fermeture de comparateur nécessite l'instanciation de chaque objet à partir de la base de données, juste pour évaluer la fermeture par rapport à chaque objet. .
Essayez donc d'écrire la même chose avec 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 (Aire de jeu):
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)
}
Sortie:
Optional("a")
Optional("b")
Optional("c")
Dans Swift, vous pouvez utiliser une nouvelle approche. Essayez d'utiliser la méthode triée à la place de sortArrayUsingComparator comme ceci ...
var sortedArray = results.sorted {
(obj1, obj2) -> Bool in
return obj1.count! > obj2.count!
}
au cas où vous avez un objet personnalisé et que vous souhaitez trier par date
let sortedArray = self.posts.sorted {
(obj1, obj2) -> Bool in
return (obj1 as! PostModel).orderCancellionDate.compare( (obj2 as! PostModel).orderCancellionDate) == .orderedDescending
}