5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Swift の Comparable プロトコルを基礎から

Last updated at Posted at 2019-05-27

この記事は何?

前回は、Equatable プロトコルを扱いました。
今回は、続きとも言える Comparable プロトコルです。

実行環境

Xcode10.2.1
Swift5.x

ハンズオン

Playground で動作確認しました。

こんな型があったとして

フルーツを表現する Fruit 型です。
3つのプロパティ name, emoji, sugarContent があります。

フルーツ型
struct Fruit {
    var name: String
    var emoji: String
    var sugarContent: Int    // フルーツの甘さ(糖度)
}

let apple  = Fruit(name: "Apple",  emoji: "🍎", sugarContent: 15)
let banana = Fruit(name: "Banana", emoji: "🍌", sugarContent: 10)
let cherry = Fruit(name: "Cherry", emoji: "🍒", sugarContent: 3)

なお、実際の各種フルーツとその糖度と比較して、上記コードの値がどうかは知りません。
配列 fruits に並べてみましょう。

フルーツの配列
let fruits = [apple, banana, cherry]    // [🍎, 🍌, 🍒]

甘いフルーツ(つまり、糖度が高い)順に並べ替えらるようにします。

小さいかどうか、大きいかどうか

「どっちが大きいか」は、逆にいうと「小さいかどうか」ってこと。
< 演算子です。
「小さいかどうか」が調べらることを保証するのが Comparable プロトコルです。

Comparable プロトコルに準拠していないオブジェクトの大小関係を比較すると...

Fruitオブジェクトの大小関係
apple < banana
スクリーンショット 2019-05-28 1.42.00.png エラーになります。 「何を基準に大きいか・小さいかを判断したらイイか」が定義されていないんですね。

Comparable の要件

Comparable プロトコルに準拠するには、2つの要件を満たす必要があります。

  1. Equatable であること
  2. < メソッドを実装していること

1.Equatableに準拠させる

1つ目の要件を満たすため、型を Equatable にします。
詳しくは前回の投稿を。

Equatableに準拠したFruit型
struct Fruit: Equatable {
    var name: String
    var emoji: String
    var sugarContent: Int
    
    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.emoji == rhs.emoji
    }
}

2. < メソッドを実装する

プロトコルを列挙したら、< 静的メソッドを実装します。
このメソッド内で、「何を基準に大小関係を判断するか」を定義します。
Fruit 型では糖度を表現する sugarContent の値で大小比較することにします。

<を実装したFruit型
struct Fruit: Equatable, Comparable {
    var name: String
    var emoji: String
    var sugarContent: Int
    
    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.emoji == rhs.emoji
    }
    
    // 小さいかどうかをBoolで返す
    static func < (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.sugarContent < rhs.sugarContent
    }
}

糖度を比較する

もう一度、applebanana より小さいかどうかを比較します。

リンゴとバナナの糖度
apple < banana    // true

apple.sugarContent5で、banana.sugarContent10 なので true が得られるようになりました。
大きいかどうかの演算子 > はどうでしょうか?

大きいかどうか
apple > banana    // false

> メソッドは実装していませんが、自動的に呼び出せるようになっています。

配列をソートする

それでは、糖度が高い順に fruits 配列をソートします。
Array 型に用意されている sorted(by:) メソッドを使いましょう。

甘い順にソートして出力
print( fruits.sorted(by: >) )    // [🍒, 🍌, 🍎]

コンソールには [🍒, 🍌, 🍎] が出力されます。
CustomStringConvertible プロトコル準拠が前提です。こちらで解説。)
糖度が高い順に並べ替えができました。

5
6
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?