Comparable
本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 39 课,共 57 课。
Comparable 为类型提供 <、<=、> 和 >= 运算符。你只需要实现 <,Swift 会自动推导其余运算符。符合 Comparable 的类型可以使用 sorted() 排序,也可以与 min() 和 max() 一起使用:
struct Version: Comparable {
let major: Int, minor: Int
static func < (lhs: Version, rhs: Version) -> Bool {
(lhs.major, lhs.minor) < (rhs.major, rhs.minor)
}
}
let versions = [Version(major: 2, minor: 1), Version(major: 1, minor: 9), Version(major: 2, minor: 0)]
let newest = versions.max()!
print("\(newest.major).\(newest.minor)")
print(versions.sorted().map { "\($0.major).\($0.minor)" })输出:
2.1
["1.9", "2.0", "2.1"]比较元组时,会按顺序比较其中的部分,因此多键比较可以写得很简洁。这里先按优先级排序,再按名称排序:
struct Task: Comparable {
let priority: Int
let name: String
static func < (lhs: Task, rhs: Task) -> Bool {
(lhs.priority, lhs.name) < (rhs.priority, rhs.name)
}
}
let tasks = [Task(priority: 2, name: "email"), Task(priority: 1, name: "fix"), Task(priority: 2, name: "call")]
print(tasks.sorted().map { $0.name })输出:
["fix", "call", "email"]不带关联值的枚举可以遵循 Comparable,而无需编写 <:各个枚举项会按照声明顺序进行比较:
enum Priority: Comparable {
case low, medium, high
}
print(Priority.low < Priority.high)
print([Priority.high, .low, .medium].sorted())输出:
true
[main.Priority.low, main.Priority.medium, main.Priority.high]sorted(by:) 可以在一次调用中按任意规则排序,而 Comparable 定义了类型的自然顺序,sorted()、min() 和 max() 都会在任何地方使用这个顺序:
struct Task: Comparable {
let priority: Int
let name: String
static func < (lhs: Task, rhs: Task) -> Bool { lhs.priority < rhs.priority }
}
let tasks = [Task(priority: 3, name: "c"), Task(priority: 1, name: "a")]
print(tasks.sorted().map { $0.name })
print(tasks.sorted(by: >).map { $0.name })输出:
["a", "c"]
["c", "a"]挑战
简单让 Runner(包含姓名和以 minutes、seconds 表示的完成时间)遵循 Comparable,其中用时更短的成绩更小,用时相同则按姓名排序。完成 podium(_:),使用 sorted() 对选手排序,并为前三名返回格式为 1. Ada 20:05 的行(选手不足三名时返回相应数量的行),秒数补足为两位。
提供的代码会读取格式为 name,mm:ss 的行,并打印返回的每一行。
你的代码应写在 Runner.swift 和 Functions.swift 中。main.swift 中包含提供的输入和输出代码,不能编辑。
亲手试试
// 提供的输入和输出代码:保持原样。
var input: [String] = []
while let line = readLine() { input.append(line) }
let runners = input.map { line -> Runner in
let p = line.split(separator: ",").map(String.init)
let t = p[1].split(separator: ":").map { Int($0)! }
return Runner(name: p[0], minutes: t[0], seconds: t[1])
}
for line in podium(runners) { print(line) }
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Swift 在线编辑器