Pythonのzip関数に相当する処理をJavaScriptで実装する方法
Pythonには、複数のイテラブルをまとめてタプル(組)の配列を作るzip関数が標準で用意されています。本記事では、このzip関数と同等の動作をする関数をJavaScriptで実装する方法を解説します。
つまり、同じ長さを持つ複数の配列が与えられたとき、対応する要素同士をペア(組)にした配列を生成する必要があります。
やりたいこと
例えば、次のような3つの配列があるとします。
const array1 = [1, 2, 3]; const array2 = ['a', 'b', 'c']; const array3 = [4, 5, 6];
これらに対してPythonのzipのような処理を行うと、出力は次のようになることが期待されます。
const output = [[1, 'a', 4], [2, 'b', 5], [3, 'c', 6]];
各配列の同じ位置にある要素が、ひとつの配列にまとめられているのが分かりますね。
実装方法
この機能は、reduce()メソッドやmap()メソッド、あるいは単純な入れ子のforループなど、さまざまな方法で実現できます。ここでは、入れ子になったforEach()ループを使ってzip()関数を実装してみましょう。
サンプルコード
const array1 = [1, 2, 3];
const array2 = ['a', 'b', 'c'];
const array3 = [4, 5, 6];
const zip = (...arr) => {
const zipped = [];
arr.forEach((element, ind) => {
element.forEach((el, index) => {
if (!zipped[index]) {
zipped[index] = [];
}
zipped[index][ind] = el;
});
});
return zipped;
};
console.log(zip(array1, array2, array3));コードのポイント
可変長引数...arrを受け取ることで、任意の数の配列に対応できるのがこの実装の強みです。外側のforEach()が「何番目の配列か」(インデックス ind)を、内側のforEach()が「その配列内での位置」(インデックス index)を追跡し、zipped[index][ind] の場所へ要素を格納していきます。結果として、行と列が入れ替わった転置のような構造が完成します。
実行結果
コンソールに出力される結果は以下の通りです。
[ [ 1, 'a', 4 ], [ 2, 'b', 5 ], [ 3, 'c', 6 ] ]
補足:map()を使ったより簡潔な実装
すべての配列の長さが同じであることが保証されているなら、map()を使えばさらに簡潔に書くこともできます。
const zip = (...arr) => {
return arr[0].map((_, i) => arr.map(array => array[i]));
};
console.log(zip(array1, array2, array3));
// [ [ 1, 'a', 4 ], [ 2, 'b', 5 ], [ 3, 'c', 6 ] ]最初の配列の長さを基準にループし、各位置 i で全配列から同じインデックスの要素を取り出すだけです。コード量が少なく読みやすいため、実務ではこちらの書き方が好まれることも多いでしょう。
-
JavaScriptの関数プロトタイプとは?仕組みと使い方を解説
JavaScriptで作成されたすべての関数には、JavaScriptエンジンによって自動的にprototypeプロパティが追加されます。このprototypeプロパティはオブジェクトであり、デフォルトではconstructorプロパティを含んでいます。関数のプロトタイプには、以下のようにしてアクセスできます。functionName.prototypeコンストラクタ関数を使ってオブジェクトを生成する場合、このprototypeプロパティを活用することで、同じコンストラクタから作成された複数のオブジェクト間でメソッドやプロパティを効率的に共有することができます。これにより、各インスタンスごとに
-
JavaScriptでのメソッド借用:call()・apply()・bind()の使い方を解説
JavaScriptでは、call()、apply()、bind()という3つのメソッドを使うことで、あるオブジェクトが持つメソッドを別のオブジェクトが「借用」できます。これは、本来そのメソッドを持たないオブジェクトに対して、thisの参照先を差し替えてメソッドを実行できる便利なテクニックです。 3つのメソッドの違い call():引数をカンマ区切りで個別に渡し、即座に関数を実行します。 apply():引数を配列(または配列風オブジェクト)として渡し、即座に関数を実行します。 bind():thisを固定した新しい関数を返すだけで、即座には実行されません。返された関数は後から好きなタイミン