Swift:按字母顺序对对象数组进行排序

176

我有这个:

class Movies {
  Name:String
  Date:Int
}

我有一个 [Movies] 数组,如何按名称字母顺序对数组进行排序?我已经尝试过:

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

以及

movieArr = sorted(movieArr)

但这并不起作用,因为我没有访问 Movies 的名称属性。

7个回答

386
在传递给sort的闭包中,比较您想要排序的属性。像这样:
movieArr.sorted { $0.name < $1.name }

或者在你想要绕过案例的情况下,可以采用以下方法:


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

旁注:通常只有类型以大写字母开头;我建议使用namedate,而不是NameDate


例如,在游乐场中:

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将按照顺序[movieA, movieB, movieC]排列。

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

1
使用 movies.sort 而不是 movies.sorted @Mike S - user2707185
@julian-król 您在答案中忘记将另一个'sorted'编辑为'sort'。注意:这不是打字错误,'sorted'在Swift 1中是正确的,但在Swift 2中变为'sort'。 - Eric Aya
1
谢谢解释。我改进了我的编辑,应该没问题了,请看一下 :) - Julian
12
注意,当对大小写有可能不一致的字符串进行排序时,这种方法是无法奏效的。通过比较.lowercaseString 可以解决这个问题。 - Matthieu Riegler
2
@EricAya 注意,在Swift 3中它又被sorted了:D。 - dvp.petrov
显示剩余6条评论

56

使用Swift 3,你可以选择以下方式之一来解决你的问题。


1. 使用不符合Comparable协议的Movie类和 sorted(by:​) 方法

如果你的Movie类不符合Comparable协议,你必须在闭包中指定你想要使用数组的sorted(by:​)方法的属性。

Movie类声明:

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
    }

}

使用方法:

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. 使用实现了 Comparable 协议的 Movie 类型和 sorted(by:​) 方法

如果你让你的 Movie 类型实现了 Comparable 协议,那么当你想使用 Array 的 sorted(by:​) 方法时,你可以写出更加简洁的代码。

Movie 类型的声明:

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
    }

}

用法:

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. 使用符合Comparable协议的Movie类与sorted()方法

通过使你的Movie类符合Comparable协议,你可以使用数组的sorted()方法代替sorted(by:)

Movie类声明:

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
    }

}

使用方法:

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

嘿,除了 movies.sorted(by: <)movies.sorted() 之外,第二个和第三个有什么区别吗? - Kamaldeep singh Bhatia
sorted(by:)sorted()是两种不同的方法。您可以使用array.sorted()作为array.sorted(by: <)的替代方案。 - Imanou Petit
是的,只是问一下,如果类定义需要改变吗?我的意思是,我们可以为 sorted(by:)sorted() 使用相同的类定义吗? - Kamaldeep singh Bhatia
1
是的,您可以拥有相同的类/结构实现,但无论如何都必须符合“Comparable”协议。 - Imanou Petit
我有一个包含自定义对象的数组,当我按升序排序时,它没有按正确的方式排序。"1" "14""28""31""4""42""49" - Krunal Nagvadia
但它应该是["1""4""14""28""28""31""42""49"] - Krunal Nagvadia

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

在长时间的尝试后,添加.lowercased()对我起了作用。我不明白为什么,因为所有文本一开始都是小写的。 - Tom Tallak Solbu
当使用lowercased()时,会将所有名称更改为小写以便正确排序 :) - Marwan Alqadi

14

对于使用Swift 3的用户,接受答案的等效方法是:

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

3

由于未使用基于语言环境的比较进行排序,大多数答案都是错误的。请查看localizedStandardCompare()。


1

已排序数组
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!
    }*

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接