JavaScriptで配列をRubyのようにスライスできたらちょっと面白いかな、と思って書いてみました。
ES6で追加されると期待したい Proxy
を使っていますので、ChromeかFirefoxでしか動きません。(もっともこの記事はOperaで書いてますが…)
slicer.jsというコードにまとめたのですが、意外と長くなってしまったので Gist に置いておきます。
使い方はこんな感じ。
var
arr = [0,1,2,3,4,5,6,7,8,9], //元となる配列
sli = toSlicer(arr); //配列を拡張
// 範囲代入と取得
sli["1..3"] = [10,11,12];
console.log(sli["0..2"]); //=>0,10,11
//複数代入と取得
sli["4,6,8"] = [13,14,15];
console.log(sli["4,5,7,9"]); //=>13,5,7,9
//Arrayのメソッドやプロパティ―ももちろん呼べる
sli.push(16);
console.log(sli.length); //=>11
//元となった配列を破壊的に参照してたりする
console.log(arr); //=> 0,10,11,12,13,5,14,7,15,9,16
破壊的なのは仕様です。
なんか、Rubyみたくといったわりに複数代入とか勝手に追加してたりしてすみません。
ですが、この複数代入が結構便利だったりします。
例えばこんな感じ。
// 配列のスワップ
sli["1,2"] = sli["2,1"];
どうでしょうか。直観的で良くないですか?
でもまあ、これだと文字列でべたに書いてて実際使うとなるとかなり微妙です。
なので、JavaScriptの暗黙の型変換を利用して、こんな風に書くこともできます。
var
i = 1,j = 2;
sli[[i,j]] = sli[[j,i]];
重要なのは sli[[i,j]]
の外側の角括弧は配列の参照で、内側の角括弧は配列リテラルとなっていることです。
これを利用してバブルソートを書いてみると、こうなります。
/**
* Slicerを使った破壊的なバブルソート
* @param {Array} ソートする配列
*/
function bubbleSort(arr) {
var
sli = toSlicer(arr),
i,j,len = sli.length;
for(i = 0; i < len; i++) {
for(j = len-1; j >= 0; j--) {
if(sli[j] < sli[i]){
//スワップ
sli[[i,j]] = sli[[j,i]];
}
}
}
return arr;
}
スワップをべたに書いたり、関数にするよりいい感じですよね。
最後に、書いておきますが、この記事はネタです。slicer.jsは実開発で使えるようなほどよくできたコードにはなっていません。
それに Proxy
の仕様はまだまだ流動的です。
Proxy
流行ったらいいな。