2015-01-09 15 views
14

スウィフトの列挙型をその定義順で比較する方法に関するドキュメントを見つける/理解するのが難しかった。私のようなスウィフト列挙の順序と比較

enum EnumType { 
    case First, Second, Third 
} 
スウィフトは、私が直接順序で列挙型を比較す​​ることはできません

、など

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // error 

が、それはコンパイルエラーが発生列挙を作成するときに具体的に、「引数リストで 『<』を呼び出すことはできませんタイプ{EnumType、EnumType}のの。私が見つけた唯一の解決策は、これはすべてが順調である

enum EnumType : Int { 
    case First = 0, Second, Third 
} 

func <(a: EnumType, b: EnumType) -> Bool { 
    return a.rawValue < b.rawValue 
} 

let type1 = EnumType.First 
let type2 = EnumType.Second 
if type1 < type2 {println("good")} // Returns "good" 

として過負荷、と私自身の比較演算子を書くことですのでアプリケーションで多くの使用と価値を持っている "重量のある"列挙型には適していますが、私が使用したいと思うかもしれないすべての演算子のオーバーロードは、軽量の列挙型のために過度に負担になります。単一の小さなモジュールの定数。

私のプロジェクトで定義するすべての列挙型の定型的なオーバーロードコードをたくさん書かずにこれを行う方法はありますか?さらに、Swiftが関連型を持たない単純な列挙型の比較演算子を自動的に提供するように、欠けているものがあります。タイプされていないか、Intとして型付けされていますか? SwiftはIntsを比較する方法を知っているので、なぜenum Intsを比較できないのですか?

+1

[この回答](http://stackoverflow.com/a/27094973/148357)で説明されているように、「hashValue」プロパティを使用できます。最後の文を必ず読んでください:) – Antonio

答えて

35

列挙型に根本的な型を与える限り、それはプロトコルRawRepresentableに準拠します。

これは、あなたが生の表現である任意のタイプのための一般的な比較演算子を書くことができることを意味し、かつ、同程度であるので、のような生のタイプがあります:あなたの列挙型は自動的に<を持つことになります意味します

func <<T: RawRepresentable where T.RawValue: Comparable>(a: T, b: T) -> Bool { 
    return a.rawValue < b.rawValue 
} 

オペレータ:

enum E: Int { // this would work with Double and String also 
    // btw, no need to give a seed value of 0, 
    // that happens automatically for Ints 
    case A, B, C, D, E 
} 

E.A < E.C // returns true 

あなたがそれを必要とする汎用アルゴリズムでそれを使用したい場合には、あなたがまだ行う必要があるでしょう定型のビットのみがComparableとしてタグあなたの列挙型です。

extension E: Comparable { } 
// (no need for anything else - requirements are already fulfilled) 

let a: [E] = [.C, .E, .A] 
let b = sorted(a) 
// b will now be [.A, .C, .E] 

、それはまた、(標準ライブラリで提供される)自動的に<=>、および>=演算子を与えるComparableに準拠して作成。

+7

enumとしてenum E:Int、Comparable {..}を記述することができます。 –

+0

このアプローチは、文字列列挙型の正しい順序を返しますか(例: "Z"、大文字の "A")?私は、比較演算子が "Z"> "A"を返すことを提案します。 – brigadir

6

これは、ある程度は、OPと同じ答えが自分自身を提案したものです。それはあなたが比較可能にしたいすべての列挙型のための定型コードを少し含んでいますが、私はすべての列挙型に匹敵するいくつかの外部の魔法の機能を持つよりも好きです。あるプログラムから別のプログラムに素早くコピー&ペーストして、列挙型が機能せず、その理由を覚えていないと問題が発生する可能性があります。

public enum LogLevel: Int, Comparable { 
    case verbose 
    case debug 
    case info 
    case warning 
    case error 
    case severe 

    // Implement Comparable 
    public static func < (a: LogLevel, b: LogLevel) -> Bool { 
     return a.rawValue < b.rawValue 
    } 
} 

EDIT:

これは@JasonMooreによってコメントに反応しています。

相当品は==を必要としません。これはEquatableで必要とされ、Swift標準ライブラリはほとんどの種類の列挙型に対してEquatableを自動的に提供します。

http://www.jessesquires.com/blog/swift-enumerations-and-equatable/

>については

、< =と> =、アップルのドキュメントは、それらが同等で必要とされていることを述べていますが、デフォルトの実装が提供されていること(==を使用すると<に基づいて、私は仮定) 。

https://developer.apple.com/documentation/swift/comparable

は、ここで私はIBMスウィフトサンドボックスで実行したコードのビットだ - それがコンパイルされ、上記の定義と細かい動作します。

let a : LogLevel = LogLevel.verbose 
let b : LogLevel = LogLevel.verbose 
let c : LogLevel = LogLevel.warning 

print(a == b) // prints true 
print(a > c) // prints false 
print(a <= c) // prints true 
+1

Comparableに準拠するには、メソッド '<=', '> ='と '>'を追加する必要があります。ボイラープレートの厄介な量です。 –

+1

@JasonMoore私が追加した編集をご覧ください。 – RenniePet

+2

あなたは正しいです。 'Equatable'は自動的にenumに自動的に追加されます(変数を持つenumの場合を除いて)。また、 '<'を実装するだけでComparableに準拠することができます。それを明確にしてくれてありがとう。 (上記の私のコメントを削除する必要がありますか?) –

関連する問題