配列を無理やり(破壊的/非破壊的)に操作する


配列操作を行う際には、破壊的操作と非破壊的操作がありますが、時には入れ替えたくなる時もあります。

破壊的操作と非破壊的操作

改めての説明は不要かもしれませんが、配列などのオブジェクトを操作する方法として、2つが考えられます。

  • 破壊的操作…もとのオブジェクトを直接書き換える
  • 非破壊的操作…新しいオブジェクトを作って返す

Rubyの標準ライブラリではmapmap!sortsort!のように、両方用意してあることも多いのですが、JavaScriptではmapは非破壊的なものだけ、sortは破壊的なものだけとなっています。

もちろん、破壊的/非破壊的に合わせた処理ができればそれが手っ取り早いのでしょうが、ときには破壊的操作をするメソッドを、非破壊的に使わないといけない、あるいはその逆、という場面も発生してしまいます。

破壊的メソッドを非破壊的に使う

こちらは簡単で、「配列をコピーしてからコピーに破壊的操作を加える」という手順でできます。

Rubyであれば、それ専用のArray#dupがありますし、JavaScriptの場合は配列の一部を取り出すArray.prototype.sliceを引数無しで呼び出せば、全部を取り出せます。

非破壊的メソッドを破壊的に使う

オブジェクトの参照を入れ替えられないなどの事情で、もとの配列を変えるしかないのに、得られた値は別の配列になってしまっている、という状況のときにも、なんとかする方法はあります。

Rubyでは、ちょうどArray#replaceというメソッドがあって、配列の中身を別な配列のものにごっそり入れ替えることができます。

JavaScriptの場合、

  1. arr.length = 0;として配列をリセットする
  2. arr.push.apply(arr, other_arr);、ES6ならarr.push(...other_arr);として、別な配列を流し込む

ことで、配列の中身を入れ替えられます(なお、疎な配列やプロトタイプが入れ替わっているものなど、特殊な配列はうまく動かないかもしれないので、ご注意ください)。