Skip to content

Latest commit

 

History

History
84 lines (65 loc) · 3.55 KB

2022-11-10-all.md

File metadata and controls

84 lines (65 loc) · 3.55 KB
title emoji type topics published
[Swift] 空配列の allSatisfy と contains の判定には注意せよ
🕊
tech
Swift
true

伝えたいこと

  • 空配列に対する allSatisfycontains の判定の違い
    • allSatisfy: 配列にひとつでも false があれば false
      • -> 空配列には false はないので true
    • contains: 配列にひとつでも true があれば true
      • -> 空配列には true はないので false
  • allSatisfycontains の使い分け
    • 『すべての値が true or false であるのか』を判定するなら -> allSatisfy
    • 『ひとつでも true or false があるのか』を判定するなら -> contains
  • 教訓
    • 空配列の可能性があるものを allSatisfycontains の処理をかける際は注意が必要である
    • 空配列の処理の混乱を避けるため if [判定対象の配列].empty { return true or false } で、先に処理を抜けさせるのも手である
    • allSatisfycontains を使う際に ! による否定は混乱の元なので、でできることなら避けた方がいい

空配列に対する allSatisfycontains の判定の違い

以下のように、空配列に対する allSatisfycontains の判定の結果は異なるので注意が必要になります。

[].allSatisfy { $0 } // true
[].contains { $0 } // false

この違いは、以下のような理解になります。

  • allSatisfy: 配列にひとつでも false があれば false
    • -> 空配列には false はないので true
  • contains: 配列にひとつでも true があれば true
    • -> 空配列には true はないので false

allSatisfycontains を使うときのポイント

つまるところ、[判定対象の配列].allSatisfy { $0 }![判定対象の配列].contains { !$0 } は同値となります。(たぶん)

なので、allSatisfycontains のどちらか片方だけで記述することは可能なのですが、! による否定を使うと混乱するので、どちらを使うか迷ったときは、以下のようなイメージを持つと良いと思います。

  • 『すべての値が true or false であるのか』を判定するなら -> allSatisfy
  • 『ひとつでも true or false があるのか』を判定するなら -> 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

以上になります。