🕊
[Swift] 空配列の allSatisfy と contains の判定には注意せよ
伝えたいこと
- 空配列に対する
allSatisfyとcontainsの判定の違い-
allSatisfy: 配列にひとつでもfalseがあればfalse- -> 空配列には
falseはないのでtrue
- -> 空配列には
-
contains: 配列にひとつでもtrueがあればtrue- -> 空配列には
trueはないのでfalse
- -> 空配列には
-
-
allSatisfyとcontainsの使い分け- 『すべての値が
trueorfalseであるのか』を判定するなら ->allSatisfy - 『ひとつでも
trueorfalseがあるのか』を判定するなら ->contains
- 『すべての値が
- 教訓
- 空配列の可能性があるものを
allSatisfyやcontainsの処理をかける際は注意が必要である - 空配列の処理の混乱を避けるため
if [判定対象の配列].empty { return true or false }で、先に処理を抜けさせるのも手である -
allSatisfyやcontainsを使う際に!による否定は混乱の元なので、でできることなら避けた方がいい
- 空配列の可能性があるものを
空配列に対する allSatisfy と contains の判定の違い
以下のように、空配列に対する allSatisfy と contains の判定の結果は異なるので注意が必要になります。
[].allSatisfy { $0 } // true
[].contains { $0 } // false
この違いは、以下のような理解になります。
-
allSatisfy: 配列にひとつでもfalseがあればfalse- -> 空配列には
falseはないのでtrue
- -> 空配列には
-
contains: 配列にひとつでもtrueがあればtrue- -> 空配列には
trueはないのでfalse
- -> 空配列には
allSatisfy や contains を使うときのポイント
つまるところ、[判定対象の配列].allSatisfy { $0 } と ![判定対象の配列].contains { !$0 } は同値となります。(たぶん)
なので、allSatisfy や contains のどちらか片方だけで記述することは可能なのですが、! による否定を使うと混乱するので、どちらを使うか迷ったときは、以下のようなイメージを持つと良いと思います。
- 『すべての値が
trueorfalseであるのか』を判定するなら ->allSatisfy - 『ひとつでも
trueorfalseがあるのか』を判定するなら ->contains
また、! による否定系を使えばワンライナーで書けるケースも、if [判定対象の配列].empty { return true or false } で判定を早期リターンさせて、複数行で書いてあげた方が読みやすいコードになると個人的には思っています。
挙動の確認
以下は、playground で実験した際のサンプルコードです。
挙動を確認したいときにお試しください。
[true, false].allSatisfy { $0 } // false
[true, true].allSatisfy { $0 } // true
[false, false].allSatisfy { $0 } // false
[].allSatisfy { $0 } // true
[true, false].allSatisfy { !$0 } // false
[true, true].allSatisfy { !$0 } // false
[false, false].allSatisfy { !$0 } // true
[].allSatisfy { !$0 } // true
[true, false].contains { $0 } // true
[true, true].contains { $0 } // true
[false, false].contains { $0 } // false
[].contains { $0 } // false
[true, false].contains { !$0 } // true
[true, true].contains { !$0 } // false
[false, false].contains { !$0 } // true
[].contains { !$0 } // false
以上になります。
Discussion