Posted at

Swiftでmap関数の引数を増やしてしまおう.

More than 5 years have passed since last update.

配列をmapするとき,mapに与えるクロージャで配列のインデックス値を使いたくなる時がある.

例えばこんなクロージャ.

{(v:Int, i:Int) in v << (24 - (i * 8))}

そして,array.map(f, 0) などと使いたくなる気分.ですが,これってなんだかmapの伝統を壊してるような気がしていやなんですよね.パッと見,なんだこれ?ってなりそうで.

APIとしてよさそうなのは,Schemeのように複数のリストを引数にとれるmap関数でしょうか.

というわけで,早速,extensionしてみました.

extension Array {

func map<U>(other: [T], transform: (T, T) -> U) -> [U] {
assert(self.count == other.count)
var v = [U]()
for i in 0 ..< self.count {
v.append(transform(self[i], other[i]))
}
return v
}
}

この例では,自分ともう一個の配列に対してクロージャを適用します.両配列サイズは同じと仮定.

[1,2,3,4].map([5,6,7,8]){$0 + $1}

// ==> [6,8,10,12]

そして,当初の配列のインデックス値を使いたいときはこんな感じ.

let array   = [1,2,3,4]

let indices = [0,1,2,3]

array.map(indices) {$0 << (24 - ($1 * 8))}

2つ以上の配列を使いたいときは,上記を元にどんどん定義していけばよさそうです.

個人的にExtensionにハマっているのと,Trailing Closureを使いたいがために上のようなことやりましたが,別に配列に組み込まなくても独立なmap関数として定義したほうがいいかもしれません.

人によっては,

map(function, array0, array1,...)

のほうが見慣れてるかも.しかも可変引数で定義できそうだし.

配列のサイズが異なる場合はどうするのがいいのかなぁ..