LoginSignup
11
11

More than 5 years have passed since last update.

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

Posted at

配列を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,...)
のほうが見慣れてるかも.しかも可変引数で定義できそうだし.

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

11
11
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11