配列の隙間を詰める関数を作ったよ
こんなことに使えるよ
JavaScriptで配列の隙間を詰める関数を作ってみました。例えば、こんな風に間にnull要素が混じる配列があったとすると。
[9,6,null,5,7,null,8]
間を詰めて、こんな風にしてくれます。
[9,6,5,7,8,null,null]
今回これを実現するためにsqueezeという関数を作りました。使い方は以下のとおりです。
var array = [9,6,null,5,7,null,8]; //対象の配列を squeeze(array); //squeeze関数に渡します
基準点を変更することもできるよ
例えば、先ほどの例は配列の前に詰めていましたが、後ろに詰めることも可能です。こんな配列があると…。
[9,6,null,5,7,null,8]
一番最後を基準にして詰めてくれます。
[null,null,9,6,5,7,8]
squeezeの使い方はこんな風になります。
var array = [9,6,null,5,7,null,8]; squeeze(array, array.length - 1); //第二引数を指定
squeezeの第二引数は、どこに向かって詰めるのか、基準となる点です。今回後ろに詰めるという話だったので、配列の一番最後の位置を指定しました。基準点を中央に設定することもできます。こんな配列があったとき。
[9,6,null,5,7,null,8]
7の要素が入っている部分、つまり配列の添え字4番を基準点として指定します。すると、この部分を基準にして配列が詰められます。
[null,9,6,5,7,8,null]
これを実現するには、以下のようなコードになります。
var array = [9,6,null,5,7,null,8]; squeeze(array, 4);
詰める対象を変更できるよ
先ほどはnullの部分を詰めていましたが、詰める対象を変更することもできます。今度は0の部分を空とみなして、詰めましょう。
[9,6,0,5,7,0,8]
上の配列を
[9,6,5,7,8,0,0]
こんな風にします。
これを実現するには、以下のようなコードになります。
var array = [9,6,null,5,7,null,8]; squeeze(array, null, 0);
第二引数は、nullを指定しています。第二引数を省略するか、nullにするか、0を指定することで、前詰めになります。そして、第三引数は空の要素とみなす値を代入します。今回はたまたま数値ですが、真偽値やオブジェクトでも大丈夫です。
これを実現するsqueeze関数のソースコードは以下のようになります。
異常が発生するとfalseが返ってきます。
/** * 配列の要素に空のものが混じっていれば、隙間を詰める * @param {Object} array 対象となる配列 * @param {Object} centerIndex(省略可能) どこを基準に配列を詰めるのか.省略すると最初の要素を基準にする. * @param {Object} emptyElement(省略可能) 何を空の要素とみなすか */ function squeeze(array, centerIndex, emptyElement){ if (!Object.isArray(array)) return false; if (centerIndex == null || !Object.isNumber(centerIndex)) centerIndex = 0; if (emptyElement == undefined) emptyElement = null; /* * 配列の隙間を詰めるアルゴリズム * 参考 http://www.geocities.jp/oldbig_ancient/KodaiHP3.htm * * 基準点を中心として、正の方向と負の方向のチェックをする */ //正の方向に対するチェック var pointer = centerIndex; //配列要素の移動先 for (var i = centerIndex; i < array.length; i++) { var currentCell = array[i]; if (i != pointer && currentCell != emptyElement) { array[pointer] = currentCell; array[i] = emptyElement; } if (array[pointer] != emptyElement) { //空っぽじゃなくなったら次に進む pointer++; } } //負の方向に対するチェック var pointer = centerIndex; //配列要素の移動先 for (var i = centerIndex; 0 <= i; i--) { var currentCell = array[i]; if (i != pointer && currentCell != emptyElement) { array[pointer] = currentCell; array[i] = emptyElement; } if (array[pointer] != emptyElement) { //空っぽじゃなくなったら次に進む pointer--; } } return true; }