Swift: ordena la matriz de objetos alfabéticamente

138

Tengo esto:

class Movies {
  Name:String
  Date:Int
}

y una gran variedad de [Películas]. ¿Cómo clasifico la matriz alfabéticamente por nombre? He intentado:

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

y

movieArr = sorted(movieArr)

pero eso no funciona porque no estoy accediendo al atributo de nombre de Películas.

Jonah Ruffer
fuente

Respuestas:

297

En el cierre al que pasa sort, compare las propiedades por las que desea ordenar. Me gusta esto:

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

o lo siguiente en los casos que desea omitir:

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

Nota al margen: por lo general, solo los tipos comienzan con una letra mayúscula; Recomiendo usar namey date, no Namey Date.


Ejemplo, en un patio de recreo:

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 estará en el orden [movieA, movieB, movieC]

Actualización Swift5

channelsArray = channelsArray.sorted { (channel1, channel2) -> Bool in
            let channelName1 = channel1.name
            let channelName2 = channel2.name
            return (channelName1.localizedCaseInsensitiveCompare(channelName2) == .orderedAscending)
Mike S
fuente
Gracias, recién estoy comenzando con Swift, y no sabía sobre el uso de cierres.
cdpalmer
1
use movies.sort en lugar de movies.sorted @Mike S
Oskariagon el
1
gracias por la explicación. Mejoré mi edición, debería estar bien, por favor, eche un vistazo :)
Julian Król
8
Cuidado, esto no funcionará al ordenar cadenas que pueden o no estar en mayúsculas. La comparación de .lowercaseStringresolverá este problema.
Matthieu Riegler
2
@EricAya Tenga en cuenta que está sorteden Swift 3 nuevamente: D.
dvp.petrov
45

Con Swift 3, puede elegir una de las siguientes formas de resolver su problema.


1. Usar sorted(by:​)con una Movieclase que no se ajusta al Comparableprotocolo

Si su Movieclase no se ajusta al Comparableprotocolo, debe especificar en su cierre la propiedad en la que desea utilizar el sorted(by:​)método Array .

Movie declaración de clase:

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
    }

}

Uso:

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. Usar sorted(by:​)con una Movieclase que se ajuste al Comparableprotocolo

Sin embargo, al hacer que su Movieclase se ajuste al Comparableprotocolo, puede tener un código mucho conciso cuando desee utilizar el sorted(by:​)método de Array .

Movie declaración de clase:

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
    }

}

Uso:

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. Usar sorted()con una Movieclase que se ajuste al Comparableprotocolo

Al hacer que su Movieclase se ajuste al Comparableprotocolo, puede usar el sorted()método de Array como alternativa a sorted(by:​).

Movie declaración de clase:

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
    }

}

Uso:

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
fuente
Oye, ¿hay alguna diferencia? entre 2do y 3ro (excepto movies.sorted(by: <)y movies.sorted())?
Kamaldeep singh Bhatia
sorted(by:)y sorted()son dos métodos diferentes. Puede usar array.sorted()como alternativa para array.sorted(by: <).
Imanou Petit
Sí, solo preguntando en caso de definición de clase, ¿necesitamos cambiar algo? Quiero decir, ¿podemos tener la misma definición de clase para ambos sorted(by:)y sorted()?
Kamaldeep singh Bhatia
1
Sí, puede tener la misma implementación de su clase / estructura que, en cualquier caso, debe ajustarse al Comparableprotocolo.
Imanou Petit
Tengo Array con customObject cuando juego en orden ascendente no se está acortando de la manera adecuada. "1" "14""28""31""4""42""49"
Krunal Nagvadia
16
let sortArray =  array.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
m.alqadi
fuente
agregar .lowercased () funcionó para mí después de un largo período de prueba. No entiendo por qué, ya que todo el texto estaba en minúscula para empezar.
Tom Tallak Solbu
cuando el uso de minúsculas () va a cambiar todos los nombres en minúsculas a ordenados correctamente :)
m.alqadi
14

Para aquellos que usan Swift 3, el método equivalente para la respuesta aceptada es:

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

Matriz ordenada Swift 4.2

arrayOfRaces = arrayOfItems.sorted(by: { ($0["raceName"] as! String) < ($1["raceName"] as! String) })
CSE 1994
fuente
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
fuente