Swift comment trier un tableau d'objets personnalisés par valeur de propriété
disons que nous avons une classe personnalisée nommée imageFile et cette classe contient deux propriétés.
class imageFile {
var fileName = String()
var fileID = Int()
}
beaucoup d'entre eux stockés dans la gamme
var images : Array = []
var aImage = imageFile()
aImage.fileName = "image1.png"
aImage.fileID = 101
images.append(aImage)
aImage = imageFile()
aImage.fileName = "image1.png"
aImage.fileID = 202
images.append(aImage)
la question Est: Comment puis-je trier le tableau d'images par 'fileID' ASC ou DESC?
15 réponses
tout d'abord, déclarez votre tableau comme un tableau dactylographié de sorte que vous puissiez appeler des méthodes lorsque vous itérez:
var images : [imageFile] = []
alors vous pouvez simplement faire:
Swift 2
images.sorted({ "151910920".fileID > .fileID })
Swift 3 & 4
images.sorted(by: { "151920920".fileID > .fileID })
l'exemple ci-dessus donne desc ordre de tri
[ mise à Jour pour Swift 3 à trier(en:) ] Ce, en exploitant une fuite de fermeture:
images.sorted { "151900920".fileID < .fileID }
où vous utilisez <
ou >
selon ASC ou DESC, respectivement. si vous voulez modifier le images
tableau , puis utiliser le suivant:
images.sort { "151910920".fileID < .fileID }
si vous allez le faire à plusieurs reprises et préférez définir une fonction, une façon est:
func sorterForFileIDASC(this:imageFile, that:imageFile) -> Bool {
return this.fileID > that.fileID
}
et ensuite utiliser comme:
images.sort(by: sorterForFileIDASC)
presque tout le monde donne comment directement, laissez-moi montrer l'évolution:
vous pouvez utiliser les méthodes d'instance de Array:
// general form of closure
images.sortInPlace({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
// types of closure's parameters and return value can be inferred by Swift, so they are omitted along with the return arrow (->)
images.sortInPlace({ image1, image2 in return image1.fileID > image2.fileID })
// Single-expression closures can implicitly return the result of their single expression by omitting the "return" keyword
images.sortInPlace({ image1, image2 in image1.fileID > image2.fileID })
// closure's argument list along with "in" keyword can be omitted, "151900920", , , and so on are used to refer the closure's first, second, third arguments and so on
images.sortInPlace({ "151900920".fileID > .fileID })
// the simplification of the closure is the same
images = images.sort({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in image1.fileID > image2.fileID })
images = images.sort({ "151900920".fileID > .fileID })
pour une explication détaillée du principe de fonctionnement du tri, voir la fonction triée .
Swift 3
people = people.sorted(by: { "151900920".email > .email })
Dans Swift 3.0
images.sort(by: { (first: imageFile, second: imageFile) -> Bool in
first. fileID < second. fileID
})
deux variantes
1) commande du tableau d'origine avec sortInPlace
self.assignments.sortInPlace({ "151900920".order < .order })
self.printAssignments(assignments)
2) utilisant un tableau alternatif pour stocker le tableau commandé
var assignmentsO = [Assignment] ()
assignmentsO = self.assignments.sort({ "151910920".order < .order })
self.printAssignments(assignmentsO)
vous pouvez aussi faire quelque chose comme
images = sorted(images) {"151900920".fileID > .fileID}
ainsi votre tableau d'images sera stocké comme trié
avec Swift 4, Array
a deux méthodes appelées sorted()
et sorted(by:)
. La première méthode, sorted()
, a la déclaration suivante:
Renvoie les éléments de la collection, triés.
func sorted() -> [Element]
la deuxième méthode, sorted(by:)
, comporte la déclaration suivante:
renvoie le éléments de la collection, triée en utilisant le prédicat que la comparaison entre les éléments.
func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
1. Trier par ordre croissant pour des objets comparables
si le type d'élément de votre collection est conforme au protocole Comparable
, vous pourrez utiliser sorted()
pour trier vos éléments dans un ordre croissant. Le code de terrain de jeu suivant montre comment utiliser sorted()
:
class ImageFile: CustomStringConvertible, Comparable {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: \(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID == rhs.fileID
}
static func <(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID < rhs.fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted()
print(sortedImages)
/*
prints: [ImageFile with ID: 100, ImageFile with ID: 200, ImageFile with ID: 300]
*/
2. Trier par ordre décroissant pour des objets comparables
si le type d'élément de votre collection est conforme au protocole Comparable
, vous devrez utiliser sorted(by:)
pour trier vos éléments par ordre décroissant.
class ImageFile: CustomStringConvertible, Comparable {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: \(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID == rhs.fileID
}
static func <(lhs: ImageFile, rhs: ImageFile) -> Bool {
return lhs.fileID < rhs.fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in
return img0 > img1
})
//let sortedImages = images.sorted(by: >) // also works
//let sortedImages = images.sorted { "151930920" > } // also works
print(sortedImages)
/*
prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100]
*/
3. Trier par ordre croissant ou décroissant pour les objets non comparables
si le type d'élément de votre collection N'est pas conforme au protocole Comparable
, vous devrez utiliser sorted(by:)
pour trier vos éléments par ordre ascendant ou descendant.
class ImageFile: CustomStringConvertible {
let fileName: String
let fileID: Int
var description: String { return "ImageFile with ID: \(fileID)" }
init(fileName: String, fileID: Int) {
self.fileName = fileName
self.fileID = fileID
}
}
let images = [
ImageFile(fileName: "Car", fileID: 300),
ImageFile(fileName: "Boat", fileID: 100),
ImageFile(fileName: "Plane", fileID: 200)
]
let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in
return img0.fileID < img1.fileID
})
//let sortedImages = images.sorted { "151940920".fileID < .fileID } // also works
print(sortedImages)
/*
prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100]
*/
notez que Swift fournit également deux méthodes appelées sort()
et sort(by:)
comme contreparties de sorted()
et sorted(by:)
si vous devez trier votre collection en place.
Swift 2 à 4
la réponse originale cherchait à trier un tableau d'objets personnalisés à l'aide d'une propriété. Ci-dessous, je vais vous montrer quelques façons pratiques de faire ce même comportement avec les structures de données swift!
petites choses hors du chemin, j'ai changé ImageFile si légèrement. Avec cela à l'esprit, je crée un tableau avec trois fichiers image. Notez que les métadonnées sont une valeur optionnelle, passant par nil comme un paramètre est attendu.
struct ImageFile {
var name: String
var metadata: String?
var size: Int
}
var images: [ImageFile] = [ImageFile(name: "HelloWorld", metadata: nil, size: 256), ImageFile(name: "Traveling Salesmen", metadata: "uh this is huge", size: 1024), ImageFile(name: "Slack", metadata: "what's in this stuff?", size: 2048) ]
ImageFile possède une propriété nommée size. Pour les exemples suivants, je vais vous montrer comment utiliser les opérations de tri avec des propriétés comme la taille.
de la plus petite à la plus grande taille (<)
let sizeSmallestSorted = images.sorted { (initial, next) -> Bool in
return initial.size < next.size
}
de la plus grande à la plus petite ( > )
let sizeBiggestSorted = images.sorted { (initial, next) -> Bool in
return initial.size > next.size
}
ensuite, nous allons trier en utilisant le nom de la propriété String. De la même manière, utilisez le tri pour comparer les chaînes. Mais notez que le bloc intérieur renvoie un résultat de comparaison. Ce résultat définira le tri.
A-Z (.ordonnance de suspension)
let nameAscendingSorted = images.sorted { (initial, next) -> Bool in
return initial.name.compare(next.name) == .orderedAscending
}
Z-A.crédits ordonnés)
let nameDescendingSorted = images.sorted { (initial, next) -> Bool in
return initial.name.compare(next.name) == .orderedDescending
}
suivant est ma façon préférée de trier, dans de nombreux cas, on aura des propriétés optionnelles. Maintenant, ne vous inquiétez pas, nous allons trier de la même manière que ci-dessus sauf que nous avons à gérer néant! En production;
j'ai utilisé ce code pour forcer toutes les instances dans mon tableau avec des valeurs de propriété nul à être dernier. Ensuite, commandez les métadonnées en utilisant les valeurs supposées non emballées.
let metadataFirst = images.sorted { (initial, next) -> Bool in
guard initial.metadata != nil else { return true }
guard next.metadata != nil else { return true }
return initial.metadata!.compare(next.metadata!) == .orderedAscending
}
il est possible d'avoir un tri secondaire pour les optionnels. Par exemple, on pourrait afficher des images avec des métadonnées et classées par taille.
Swift 4.0 et 4.1. Tout d'abord, j'ai créé un tableau mutable de type imageFile () comme indiqué ci-dessous
var arr = [imageFile]()
créer image d'objet mutable de type imageFile () et attribuer une valeur aux propriétés comme indiqué ci-dessous
var image = imageFile()
image.fileId = 14
image.fileName = "A"
Maintenant, ajoutez cet objet à array arr
arr.append(image)
maintenant, assignez les différentes propriétés à un même objet mutable I. E image
image = imageFile()
image.fileId = 13
image.fileName = "B"
maintenant, à nouveau ajouter l'objet image pour arraisonner 151990920"
arr.append(image)
maintenant, nous allons appliquer ordre ascendant sur fileId propriété dans array arr objets. Utiliser < symbole pour l'ordre ascendant
arr = arr.sorted(by: {"151950920".fileId < .fileId}) // arr has all objects in Ascending order
print("sorted array is",arr[0].fileId)// sorted array is 13
print("sorted array is",arr[1].fileId)//sorted array is 14
Maintenant, nous allons appliquer ordre Décroissant sur fileId propriété dans la gamme arr objets. Utilisez > le symbole pour L'ordre décroissant
arr = arr.sorted(by: {"151960920".fileId > .fileId}) // arr has all objects in Descending order
print("Unsorted array is",arr[0].fileId)// Unsorted array is 14
print("Unsorted array is",arr[1].fileId)// Unsorted array is 13
Dans Swift 4.1. Pour les commandes triées utiliser
let sortedArr = arr.sorted { (id1, id2) -> Bool in
return id1.fileId < id2.fileId // Use > for Descending order
}
si vous allez trier ce tableau à plus d'un endroit, il peut être logique de rendre votre type de tableau Comparable.
class MyImageType: Comparable, Printable {
var fileID: Int
// For Printable
var description: String {
get {
return "ID: \(fileID)"
}
}
init(fileID: Int) {
self.fileID = fileID
}
}
// For Comparable
func <(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID < right.fileID
}
// For Comparable
func ==(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID == right.fileID
}
let one = MyImageType(fileID: 1)
let two = MyImageType(fileID: 2)
let twoA = MyImageType(fileID: 2)
let three = MyImageType(fileID: 3)
let a1 = [one, three, two]
// return a sorted array
println(sorted(a1)) // "[ID: 1, ID: 2, ID: 3]"
var a2 = [two, one, twoA, three]
// sort the array 'in place'
sort(&a2)
println(a2) // "[ID: 1, ID: 2, ID: 2, ID: 3]"
si vous n'utilisez pas d'objets personnalisés, mais des types de valeurs qui implémentent un protocole Comparable (Int, String, etc..), vous pouvez simplement faire ceci:
myArray.sort(>) //sort descending order
un exemple:
struct MyStruct: Comparable {
var name = "Untitled"
}
func <(lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.name < rhs.name
}
// Implementation of == required by Equatable
func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.name == rhs.name
}
let value1 = MyStruct()
var value2 = MyStruct()
value2.name = "A New Name"
var anArray:[MyStruct] = []
anArray.append(value1)
anArray.append(value2)
anArray.sort(>) // This will sort the array in descending order
si vous voulez trier le tableau original des objets personnalisés. Voici une autre façon de le faire dans Swift 2.1
var myCustomerArray = [Customer]()
myCustomerArray.sortInPlace {(customer1:Customer, customer2:Customer) -> Bool in
customer1.id < customer2.id
}
où id
est un entier. Vous pouvez également utiliser le même opérateur <
pour les propriétés String
.
Vous pouvez en apprendre plus sur son utilisation en regardant un exemple ici: Swift2: Clients Proches
var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort(by: >)
print(students)
Imprime : "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
je fais comme ça et ça fonctionne:
var images = [imageFile]()
images.sorted(by: {"151900920".fileID.compare(.fileID) == .orderedAscending })