Swift: Sortuj tablicę obiektów alfabetycznie


137

Mam to:

class Movies {
  Name:String
  Date:Int
}

i tablicę [Movies]. Jak posortować tablicę alfabetycznie według nazwy? Próbowałem:

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

i

movieArr = sorted(movieArr)

ale to nie działa, ponieważ nie mam dostępu do atrybutu nazwy filmów.

Odpowiedzi:


297

W zamknięciu, do którego przejdziesz sort, porównaj właściwości, według których chcesz sortować. Lubię to:

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

lub następujące w przypadkach, w których chcesz ominąć przypadki:

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

Uwaga dodatkowa: Zazwyczaj tylko typy rozpoczynają się wielką literą; Polecam używanie namei date, nie Namei Date.


Przykład na placu zabaw:

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 będzie w kolejności [movieA, movieB, movieC]

Aktualizacja Swift5

channelsArray = channelsArray.sorted { (channel1, channel2) -> Bool in
            let channelName1 = channel1.name
            let channelName2 = channel2.name
            return (channelName1.localizedCaseInsensitiveCompare(channelName2) == .orderedAscending)

Dzięki, dopiero zaczynam od Swift i nie wiedziałem o używaniu zamknięć.
— cdpalmer

1
użyj movies.sort zamiast movies.sorted @Mike S
— Oskariagon

1
dzięki za wyjaśnienie. Poprawiłem mój montaż, powinno być dobrze, zapraszam :)
— Julian Król

8
Uwaga, to nie zadziała podczas sortowania ciągów znaków, które mogą być pisane wielkimi literami lub nie. Porównanie wyników .lowercaseStringrozwiąże ten problem.
— Matthieu Riegler

2
@EricAya Zauważ, że sortedznowu jest w Swift 3: D.
— dvp.petrov

44

Dzięki Swift 3 możesz wybrać jeden z następujących sposobów rozwiązania problemu.


1. Używanie sorted(by:​)z Movieklasą, która nie jest zgodna zComparable protokołem

Jeśli twoja Movieklasa nie jest zgodna z Comparableprotokołem, musisz określić w swoim zamknięciu właściwość, na której chcesz używać sorted(by:​)metody Array .

Movie deklaracja klasy:

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
    }

}

Stosowanie:

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. Używanie sorted(by:​)z Movieklasą zgodną z Comparableprotokołem

Jednak sprawiając, że Movieklasa jest zgodna z Comparableprotokołem, możesz mieć bardzo zwięzły kod, gdy chcesz użyć sorted(by:​)metody Array .

Movie deklaracja klasy:

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
    }

}

Stosowanie:

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. Używanie sorted()z Movieklasą, która jest zgodna zComparable protokołem

Dostosowując Movieklasę do Comparableprotokołu, możesz użyć sorted()metody Array jako alternatywy dla sorted(by:​).

Movie deklaracja klasy:

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
    }

}

Stosowanie:

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]
 */

Hej, czy jest jakaś różnica. między 2 a 3 (z wyjątkiem movies.sorted(by: <)i movies.sorted())?
— Kamaldeep singh Bhatia,

sorted(by:)i sorted()są dwiema różnymi metodami. Możesz użyć array.sorted()jako alternatywy dla array.sorted(by: <).
— Imanou Petit

Tak, po prostu pytam w przypadku definicji klasy, czy musimy cokolwiek zmieniać? Chodzi mi o to, czy możemy mieć tę samą definicję klasy dla obu sorted(by:)i sorted()?
— Kamaldeep singh Bhatia,

1
Tak, możesz mieć taką samą implementację swojej klasy / struktury, która w każdym przypadku musi być zgodna z Comparableprotokołem.
— Imanou Petit

Mam Array z customObject, kiedy pokazuję się w porządku rosnącym, to nie jest zwarcie we właściwy sposób. "1" "14""28""31""4""42""49"
— Krunal Nagvadia

16
let sortArray =  array.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })

dodanie .lowercased () zadziałało dla mnie po długim okresie prób. Nie rozumiem dlaczego, ponieważ cały tekst był od początku pisany małymi literami.
— Tom Tallak Solbu

użycie małych liter () spowoduje zmianę wszystkich nazw na małe, aby były posortowane poprawnie :)
— m.alqadi

14

W przypadku użytkowników korzystających z języka Swift 3 równoważną metodą zaakceptowanej odpowiedzi jest:

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

1

Posortowana tablica Swift 4.2

arrayOfRaces = arrayOfItems.sorted(by: { ($0["raceName"] as! String) < ($1["raceName"] as! String) })

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!
    }*
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.