Swift: trier le tableau d'objets par ordre alphabétique

138

J'ai ceci:

class Movies {
  Name:String
  Date:Int
}

et une gamme de [Films]. Comment trier le tableau par ordre alphabétique par nom? J'ai essayé:

movieArr = movieArr.sorted{ $0 < $1 }

et

movieArr = sorted(movieArr)

mais cela ne fonctionne pas car je n'accède pas à l'attribut name de Movies.

Jonah Ruffer
la source

Réponses:

297

Dans la fermeture à laquelle vous passez sort, comparez les propriétés par lesquelles vous souhaitez trier. Comme ça:

movieArr.sorted { $0.name < $1.name }

ou ce qui suit dans les cas que vous souhaitez contourner:

movieArr.sorted { $0.name.lowercased() < $1.name.lowercased() }

Note de bas de page: En général, seuls les types commencent par une lettre majuscule; Je recommanderais d'utiliser nameet date, pas Nameet Date.


Exemple, dans une aire de jeux:

class Movie {
    let name: String
    var date: Int?

    init(_ name: String) {
        self.name = name
    }
}

var movieA = Movie("A")
var movieB = Movie("B")
var movieC = Movie("C")

let movies = [movieB, movieC, movieA]
let sortedMovies = movies.sorted { $0.name < $1.name }
sortedMovies

sortedMovies sera dans l'ordre [movieA, movieB, movieC]

Mise à jour Swift5

channelsArray = channelsArray.sorted { (channel1, channel2) -> Bool in
            let channelName1 = channel1.name
            let channelName2 = channel2.name
            return (channelName1.localizedCaseInsensitiveCompare(channelName2) == .orderedAscending)
Mike S
la source
Merci, je ne fais que commencer avec Swift et je ne connaissais pas l'utilisation des fermetures.
cdpalmer
1
utilisez movies.sort au lieu de movies.sorted @Mike S
Oskariagon
1
Merci pour l'explication. Amélioration de mon montage, ça devrait aller, s'il vous plaît jeter un oeil :)
Julian Król
8
Attention, cela ne fonctionnera pas lors du tri des chaînes qui peuvent ou non être en majuscules. La comparaison de .lowercaseStringrésoudra ce problème.
Matthieu Riegler le
2
@EricAya Notez que c'est sortedà nouveau dans Swift 3: D.
dvp.petrov
45

Avec Swift 3, vous pouvez choisir l'une des méthodes suivantes pour résoudre votre problème.


1. Utilisation sorted(by:​)avec une Movieclasse non conforme au Comparableprotocole

Si votre Movieclasse n'est pas conforme au Comparableprotocole, vous devez spécifier dans votre clôture la propriété sur laquelle vous souhaitez utiliser la sorted(by:​)méthode d'Array .

Movie déclaration de classe:

import Foundation

class Movie: CustomStringConvertible {

    let name: String
    var date: Date
    var description: String { return name }

    init(name: String, date: Date = Date()) {
        self.name = name
        self.date = date
    }

}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")

let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted(by: { $0.name < $1.name })
// let sortedMovies = movies.sorted { $0.name < $1.name } // also works

print(sortedMovies)

/*
prints: [Avatar, Piranha II: The Spawning, Titanic]
*/

2. Utilisation sorted(by:​)avec une Movieclasse conforme au Comparableprotocole

Cependant, en rendant votre Movieclasse conforme au Comparableprotocole, vous pouvez avoir un code beaucoup plus concis lorsque vous souhaitez utiliser la sorted(by:​)méthode d'Array .

Movie déclaration de classe:

import Foundation

class Movie: CustomStringConvertible, Comparable {

    let name: String
    var date: Date
    var description: String { return name }

    init(name: String, date: Date = Date()) {
        self.name = name
        self.date = date
    }

    static func ==(lhs: Movie, rhs: Movie) -> Bool {
        return lhs.name == rhs.name
    }

    static func <(lhs: Movie, rhs: Movie) -> Bool {
        return lhs.name < rhs.name
    }

}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")

let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted(by: { $0 < $1 })
// let sortedMovies = movies.sorted { $0 < $1 } // also works
// let sortedMovies = movies.sorted(by: <) // also works

print(sortedMovies)

/*
 prints: [Avatar, Piranha II: The Spawning, Titanic]
 */

3. Utilisation sorted()avec une Movieclasse conforme au Comparableprotocole

En rendant votre Movieclasse conforme au Comparableprotocole, vous pouvez utiliser la sorted()méthode d'Array comme alternative à sorted(by:​).

Movie déclaration de classe:

import Foundation

class Movie: CustomStringConvertible, Comparable {

    let name: String
    var date: Date
    var description: String { return name }

    init(name: String, date: Date = Date()) {
        self.name = name
        self.date = date
    }

    static func ==(lhs: Movie, rhs: Movie) -> Bool {
        return lhs.name == rhs.name
    }

    static func <(lhs: Movie, rhs: Movie) -> Bool {
        return lhs.name < rhs.name
    }

}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")

let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted()

print(sortedMovies)

/*
 prints: [Avatar, Piranha II: The Spawning, Titanic]
 */
Imanou Petit
la source
Hé, y a-t-il des différences. entre le 2 et le 3 (sauf movies.sorted(by: <)et movies.sorted())?
Kamaldeep singh Bhatia
sorted(by:)et sorted()sont deux méthodes différentes. Vous pouvez utiliser array.sorted()comme alternative pour array.sorted(by: <).
Imanou Petit
Oui, juste demander en cas de définition de classe, devons-nous changer quelque chose? Je veux dire, pouvons-nous avoir la même définition de classe pour les deux sorted(by:)et sorted()?
Kamaldeep singh Bhatia
1
Oui, vous pouvez avoir la même implémentation de votre classe / structure qui, dans tous les cas, doit se conformer au Comparableprotocole.
Imanou Petit
J'ai Array avec customObject lorsque je shoer dans l'ordre croissant, il ne court pas correctement. "1" "14""28""31""4""42""49"
Krunal Nagvadia
16
let sortArray =  array.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
m.alqadi
la source
l'ajout de .lowercased () a fonctionné pour moi après une longue période d'essais. Je ne comprends pas pourquoi, puisque tout le texte était en minuscules pour commencer.
Tom Tallak Solbu
quand utiliser minuscules () changera tous les noms en minuscules pour être triés correctement :)
m.alqadi
14

Pour ceux qui utilisent Swift 3, la méthode équivalente pour la réponse acceptée est:

movieArr.sorted { $0.Name < $1.Name }
Jacobo Koenig
la source
1

Tableau trié Swift 4.2

arrayOfRaces = arrayOfItems.sorted(by: { ($0["raceName"] as! String) < ($1["raceName"] as! String) })
CSE 1994
la source
0
*import Foundation
import CoreData


extension Messages {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Messages> {
        return NSFetchRequest<Messages>(entityName: "Messages")
    }

    @NSManaged public var text: String?
    @NSManaged public var date: Date?
    @NSManaged public var friends: Friends?

}

    //here arrMessage is the array you can sort this array as under bellow 

    var arrMessages = [Messages]()

    arrMessages.sort { (arrMessages1, arrMessages2) -> Bool in
               arrMessages1.date! > arrMessages2.date!
    }*
Muhammad Ahmad
la source