Swiftは型がきっちりした言語であることをまず認識してください。
また、operator <
には、Intの比較,Stringの比較など多くの operator があり、コンパイラは型によってどのoperatorを使用するかを決定します。
提示の配列ですが、型を明示すると
swift
1let array: [Any] = [
2 ["A", -10],
3 ["B", 20],
4 ["C", 10]
5]
です。
つまり、コンパイラが認識するarray[1]
の型はInt
ではなくAny
です。
そのためコンパイラはどの<
を使用していいのかを決定できません。
ですので、コンパイラに型を明示してあげる必要があるのです。
明示の方法はいろいろあります。強制的なアップキャストもその一つです。
強制的なアップキャストはクラッシュの可能性もありますので、強制的なアップキャストを使わないものをいくつか例示しておきます。
普通の関数を作る。
swift
1func g(lhs: [Any], rhs: [Any], f: (Int, Int) -> Bool) -> Bool {
2
3 guard let lhs = lhs[1] as? Int else {
4
5 return false
6 }
7 guard let rhs = rhs[1] as? Int else {
8
9 return false
10 }
11
12 return f(lhs, rhs)
13}
14
15print(array.sorted { g(lhs: $0, rhs: $1, f: >) })
16print(array.sorted { g(lhs: $0, rhs: $1, f: <) })
ちょっと変わった関数を作る。
swift
1func h(f: @escaping (Int, Int) -> Bool) -> ([Any], [Any]) -> Bool {
2
3 return { lhs, rhs -> Bool in
4
5 guard let lhs = lhs[1] as? Int else {
6
7 return false
8 }
9 guard let rhs = rhs[1] as? Int else {
10
11 return false
12 }
13
14 return f(lhs, rhs)
15 }
16}
17
18
19print(array.sorted(by: h(f: >)))
20print(array.sorted(by: h(f: <)))
こういったことが面倒なので、普通は新しい型を作ってしまいます。
その方が逆に簡単になります。
例えば、
swift
1struct Info {
2
3 let name: String
4 let number: Int
5}
6extension Info: Comparable {
7
8 static func == (lhs: Info, rhs: Info) -> Bool {
9 return lhs.number == rhs.number
10 }
11
12 static func < (lhs: Info, rhs: Info) -> Bool {
13 return lhs.number < rhs.number
14 }
15}
16extension Info: CustomStringConvertible {
17
18 var description: String {
19 return "{ name: (name), number: (number) }"
20 }
21}
22
23// for this answer.
24extension Info {
25
26 init?(_ array: [Any]) {
27 guard let name = array[0] as? String else {
28 return nil
29 }
30 guard let number = array[1] as? Int else {
31 return nil
32 }
33
34 self.init(name: name, number: number)
35 }
36}
37
38let infoArray = array.compactMap { Info($0) }
39print(infoArray.sorted(by: >))
40print(infoArray.sorted(by: <))
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/06 06:08