web-dev-qa-db-fra.com

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 que cette classe contient deux propriétés.

class imageFile  {
    var fileName = String()
    var fileID = Int()
}

beaucoup d'entre eux stockés dans Array

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 les images tableau par 'FileID' ASC ou DESC?

455
mohacs

Commencez par déclarer votre tableau en tant que tableau typé pour pouvoir appeler des méthodes lorsque vous effectuez une itération:

var images : [imageFile] = []

Ensuite, vous pouvez simplement faire:

Swift 2

images.sorted({ $0.fileID > $1.fileID })

Swift 3 & Swift 4 & Swift 5

images.sorted(by: { $0.fileID > $1.fileID })

L'exemple ci-dessus donne desc ordre de tri

827
Alex Wayne

[ Mis à jour pour Swift 3 avec sort (by:) ] Ceci, exploitant une fermeture de fin:

images.sorted { $0.fileID < $1.fileID }

où vous utilisez < ou > en fonction de ASC ou DESC, respectivement. Si vous voulez modifier le tableau images, utilisez ce qui suit:

images.sort { $0.fileID < $1.fileID }

Si vous envisagez de répéter cette opération et préférez définir une fonction, vous pouvez:

func sorterForFileIDASC(this:imageFile, that:imageFile) -> Bool {
  return this.fileID > that.fileID
}

et ensuite utiliser comme:

images.sort(by: sorterForFileIDASC)
202
GoZoner

Presque tout le monde donne comment directement, laissez-moi vous 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, $0, $1, $2, and so on are used to refer the closure's first, second, third arguments and so on
images.sortInPlace({ $0.fileID > $1.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({ $0.fileID > $1.fileID })

Pour une explication détaillée du principe de fonctionnement du tri, voir La fonction triée .

51
fujianjin6471

Swift

people = people.sorted(by: { $0.email > $1.email })
42
quemeful

Avec Swift 5, 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:), a la déclaration suivante:

Renvoie les éléments de la collection, triés à l'aide du prédicat donné en tant que 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() afin de trier vos éléments par 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 en 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 dans un 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 { $0 > $1 } // also works
print(sortedImages)

/*
 prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100]
 */

# 3. Tri 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:) afin de trier vos éléments par ordre croissant ou décroissant.

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 { $0.fileID < $1.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 sur place.

31
Imanou Petit

Dans Swift 3.

images.sort(by: { (first: imageFile, second: imageFile) -> Bool in
    first. fileID < second. fileID
})
23
jaiswal Rajan

Swift 2 à 4

La réponse initiale cherchait à trier un tableau d'objets personnalisés à l'aide de certaines propriétés. Ci-dessous, je vais vous montrer quelques façons pratiques de faire le même comportement avec les structures de données w/Swift!

Les petites choses hors du chemin, j'ai légèrement modifié ImageFile. Dans cet esprit, je crée un tableau avec trois fichiers image. Notez que les métadonnées sont une valeur facultative. Null est attendu comme paramètre.

 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 a 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 telles que la taille.

du plus petit au plus gros (<)

    let sizeSmallestSorted = images.sorted { (initial, next) -> Bool in
      return initial.size < next.size
    }

du plus grand au plus petit (>)

    let sizeBiggestSorted = images.sorted { (initial, next) -> Bool in
      return initial.size > next.size
    }

Nous allons ensuite trier en utilisant le nom de la propriété String. De la même manière, utilisez sort pour comparer les chaînes. Mais remarquez que le bloc interne renvoie un résultat de comparaison. Ce résultat va définir le tri.

A-Z (.orderedAscending)

    let nameAscendingSorted = images.sorted { (initial, next) -> Bool in
      return initial.name.compare(next.name) == .orderedAscending
    }

Z-A (.orderedDescending)

    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 la plupart des 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 devons gérer zéro! En production;

J'ai utilisé ce code pour forcer la dernière à mettre toutes les occurrences de mon tableau avec des valeurs de propriété nil. Ensuite, triez les métadonnées à l'aide des valeurs non enveloppées supposé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 montrer des images avec des métadonnées et classées par taille.

17
jnblanchard

Deux alternatives

1) Commande du tableau d'origine avec sortInPlace

self.assignments.sortInPlace({ $0.order < $1.order })
self.printAssignments(assignments)

2) Utilisation d'un autre tableau pour stocker le tableau commandé

var assignmentsO = [Assignment] ()
assignmentsO = self.assignments.sort({ $0.order < $1.order })
self.printAssignments(assignmentsO)
17
Bernauer

Vous pouvez aussi faire quelque chose comme

images = sorted(images) {$0.fileID > $1.fileID}

de sorte que votre tableau d'images sera stocké comme trié

16
Nicolas Grenié

Swift 4.0, 4.1 & 4.2 Tout d'abord, j'ai créé un tableau mutable de type imageFile () comme indiqué ci-dessous

var arr = [imageFile]()

Créez une image d'objet modifiable de type imageFile () et affectez une valeur aux propriétés comme indiqué ci-dessous

   var image = imageFile()
   image.fileId = 14
   image.fileName = "A"

Maintenant, ajoutez cet objet au tableau arr

    arr.append(image)

Attribuez maintenant les différentes propriétés au même objet mutable, à savoir image.

   image = imageFile()
   image.fileId = 13
   image.fileName = "B"

Maintenant, ajoutez à nouveau l'objet image au tableau arr

    arr.append(image)

Maintenant, nous allons appliquer la propriété ordre croissant à fileId dans des objets tableau arr. Utilisez <symbole pour l'ordre croissant

 arr = arr.sorted(by: {$0.fileId < $1.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 la propriété ordre décroissant sur fileId dans des objets tableau arr. Utilisez > symbole pour l'ordre décroissant

 arr = arr.sorted(by: {$0.fileId > $1.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

In Swift 4.1. & 4.2 Pour une utilisation dans l'ordre de tri

let sortedArr = arr.sorted { (id1, id2) -> Bool in
  return id1.fileId < id2.fileId // Use > for Descending order
}
14
GSK

Si vous allez trier ce tableau à plusieurs endroits, il peut être judicieux 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]"
6
kwerle

Si vous n'utilisez pas d'objets personnalisés, mais des types de valeur qui implémentent le protocole Comparable (Int, String etc.), vous pouvez simplement procéder comme suit:

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
6
dorian

Je le fais comme ça et ça marche:

var images = [imageFile]() images.sorted(by: {$0.fileID.compare($1.fileID) == .orderedAscending })

3
Illya Krit

Vous retournez un tableau trié à partir de la propriété fileID de la manière suivante:

Swift 2

let sortedArray = images.sorted({ $0.fileID > $1.fileID })

Swift 3 OR 4

let sortedArray = images.sorted(by: { $0.fileID > $1.fileID })

Swift 5.

let sortedArray = images.sorted {
    $0.fileID < $1.fileID
}
2
Vicky Prajapati

Si vous souhaitez trier le tableau d'origine d'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
}

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 consultant un exemple ici: Swift2: Clients à proximité

2
Hanny
var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

students.sort(by: >)

print(students)

Impressions: "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"

2
Siddharth Chauhan

Swift 3 & 4 & 5

J'ai eu un problème lié aux minuscules et majuscules

alors j'ai fait ce code

let sortedImages = images.sorted(by: { $0.fileID.lowercased() < $1.fileID.lowercased() })

et ensuite utiliser les images triées après cela

0