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.