Array の functional loop (map, reduce) で、要素のindexが取りたい場面があった。
let arr: Array<String> = ["A", "B", "C", "D", "E"]
// $0 $1 を使う書き方
arr.map{ $0 + "F" }
arr.reduce("", { $0 + $1 }) //=> "ABCDE"
// 定義する書き方
arr.map{ elem in
elem + "F"
}
arr.reduce("", {acc, cur in
acc + cur
})
// どちらの書き方でも結果はそれぞれ同じ。
// map --> arr = ["AF", "BF", "CF", "DF", "GF"]
// reduce --> "ABCDE"
今回は例として、奇数番目の要素だけを "X"
にしたいとする。
loop内で要素のindexを取得し、 index % 2 == 0
か否か場合分けしたい。
調べると、swift 3.0 までは、要素が格納されている変数 (上の例だと$0
, $1
, elem
, cur
)の.0
でindexを取得できたようであった。
// swift 3.0 までで可能な書き方
arr.map { $0.0 % 2 == 0 ? "X" : elem }
swift 5.0でこれを行うと、次のようにエラーが出た。
Value of type 'String.Element' (aka 'Character') has no member '0'
解決策としては、配列を一旦 EnumeratedSequence
に変換してやる。
そうすると、全ての要素が「値とoffset(=index)のペア」に変わったシーケンスを取得できる。
値には.element
、indexには.offset
でアクセスできる。
// swift 5.0 で可能な書き方
arr.enumerated().map { $0.offset % 2 == 0 ? "X" : $0.element }
// --> arr = ["X", "B", "X", "D", "X"]