Swift: classifica a matriz de objetos em ordem alfabética

138

Eu tenho isto:

class Movies {
  Name:String
  Date:Int
}

e uma variedade de [filmes]. Como ordeno a matriz em ordem alfabética por nome? Eu tentei:

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

e

movieArr = sorted(movieArr)

mas isso não funciona porque não estou acessando o atributo name de Movies.

Jonah Ruffer
fonte

Respostas:

297

No fechamento para o qual você passa sort, compare as propriedades pelas quais deseja classificar. Como isso:

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

ou o seguinte nos casos em que você deseja ignorar os casos:

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

Nota: Normalmente, apenas os tipos começam com uma letra maiúscula; Eu recomendo usar namee date, não Namee Date.


Exemplo, em um playground:

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á na ordem [movieA, movieB, movieC]

Atualização Swift5

channelsArray = channelsArray.sorted { (channel1, channel2) -> Bool in
            let channelName1 = channel1.name
            let channelName2 = channel2.name
            return (channelName1.localizedCaseInsensitiveCompare(channelName2) == .orderedAscending)
Mike S
fonte
Obrigado, estou apenas começando com Swift e não sabia sobre o uso de fechamentos.
cdpalmer
1
use movies.sort em vez de movies.sorted @Mike S
Oskariagon
1
Obrigado pela explicação. Melhorou a minha edição, deve estar bem, por favor, dê uma olhada :)
Julian Król
8
Cuidado, isso não funcionará ao classificar a sequência que pode ou não ser maiúscula. Comparando o .lowercaseStringirá resolver este problema.
Matthieu Riegler 26/02
2
@EricAya Observe que está sortedno Swift 3 novamente: D.
precisa saber é o seguinte
45

Com o Swift 3, você pode escolher uma das seguintes maneiras de resolver seu problema.


1. Usando sorted(by:​)com uma Movieclasse que não está em conformidade comComparable protocolo

Se sua Movieclasse não estiver em conformidade com o Comparableprotocolo, você deverá especificar no seu fechamento a propriedade na qual deseja usar o Arraysorted(by:​) método .

Movie declaração 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
    }

}

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. Usando sorted(by:​)com uma Movieclasse que esteja em conformidade com o Comparableprotocolo

No entanto, tornando sua Movieclasse conforme o Comparableprotocolo, você pode ter um código muito conciso quando quiser usar o sorted(by:​)método Array .

Movie declaração 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
    }

}

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. Usando sorted()com uma Movieclasse que esteja em conformidade com o Comparableprotocolo

Fazendo sua Movieclasse estar em conformidade com o Comparableprotocolo, você pode usar o sorted()método Array como uma alternativa ao sorted(by:​).

Movie declaração 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
    }

}

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
fonte
Ei, há alguma diferença. entre 2 e 3 (exceto movies.sorted(by: <)e movies.sorted())?
Kamaldeep singh Bhatia
sorted(by:)e sorted()são dois métodos diferentes. Você pode usar array.sorted()como uma alternativa para array.sorted(by: <).
Imanou Petit
Sim, apenas perguntando em caso de definição de classe, precisamos mudar alguma coisa? Quero dizer, podemos ter a mesma definição de classe para ambos sorted(by:)e sorted()?
Kamaldeep singh Bhatia
1
Sim, você pode ter a mesma implementação de sua classe / estrutura que, em qualquer caso, precisa estar em conformidade com o Comparableprotocolo.
Imanou Petit
Eu tenho Array com customObject quando tiro em ordem crescente, não está em curto da maneira correta. "1" "14""28""31""4""42""49"
Krunal Nagvadia 17/08/19
16
let sortArray =  array.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
m.alqadi
fonte
adicionar .lowercased () funcionou para mim depois de um longo período de tentativas. Não entendo o porquê, já que todo o texto estava em minúsculas.
Tom Tallak Solbu
quando o uso em minúsculas () irá alterar todos os nomes para minúsculas para classificadas corretamente :)
m.alqadi
14

Para aqueles que usam o Swift 3, o método equivalente para a resposta aceita é:

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

Classificação ordenada Swift 4.2

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