SwiftのArrayにある便利なメソッド(first, last, etc.)の注意点

投稿者: | 2019年8月3日

SwiftのArrayにある便利なメソッド(firstIndex, lastIndex, etc.)の注意点

SwiftのArrayにはある条件を満たす要素やそのインデックスを返してくれるものがあり、forループなどで回すよりモダンで処理が分かりやすい。

それがインスタンスメソッドとしてArrayに装備されている、first(where:条件)やlast(where:条件)のようなものである。
インデックスを返すfirstIndex(where:条件)やlastIndex(where:条件)もある。JavaやKotlinにもほぼ同じものがある。

例えばDate型の要素を持つ配列targetDateの中から指定されたtheDateに最も近い直前のインデックスを持つものを印字すると言うものを考える。ありがちな状況だが、最初と最後で年をまたぐ処理が必要となっている。

if let i = targetDate[dateForDecomposition.year-2018].firstIndex(where: {$0 > theDate}){
    if i == 0 {
        if let printdate = targetDate[dateForDecomposition.year-2019].last{
            print(format.string(from: printdate))
        }
    } else if let printdate = targetDate[dateForDecomposition.year-2018][i-1]{
        print(format.string(from: printdate))
    }
} else {
    if let printdate = targetDate[dateForDecomposition.year-2018].last{
        print(format.string(from: printdate))
    }
}

ここで注意すべき事が2点ある。

  1. この例で言うと、与えた年月日の「年」がiを正しく与えうる範囲に入っていると確信があっても1行目のif文に対するelseの処理を書くのを忘れないこと。Try-Cactch的な辻褄をちゃんと合わせておくことである。

  2. このfirst, lastの特徴として端点まで行って端点ギリギリで満たす要素(インデックス)が見つかると人間の目では考えられる場合でもelseセクションに回されてしまうことがあること。

特に2.には悩まされた。これは「等しい」という事に対する仕様なのかも知れない。人間は「A=B」とみなしても、プログラミング言語ではそう判断しない、という事は往々にしてある。他の言語にも同じような枠組みがあるので、使うときには同様の注意を払いたいと思った。

またこれらのメソッドはArrayだけではなく、Collection全般に付随しているので必要に応じて調べ、積極的に利用したい。

コメントを残す