多次元配列に対する従来のアプローチの何が問題になっていますか?
function ArrayND(size, N, fill) {
if (N < 1) throw new Error('Arrays must have at least one dimension.');
if (size < 1) throw new Error('Arrays must have at least one element.');
var arr = new Array(size);
populate(arr, 1);
function populate(a, depth) {
for (var i = 0; i < size; i++) {
if (depth < N) {
a[i] = new Array(size);
populate(a[i], depth+1);
} else a[i]=fill;
}
}
return arr;
}
これは、より直感的にアクセスできる多次元配列 (オプションでデフォルト値が入ります) を返します。
var arr = ArrayND(5, 3, 'hi');
console.log(arr[0][1][2]); // => 'hi'
arr[0][1][3] = 'mom';
更新:あなたの目標は、任意の長さの引数を指定して多次元配列にアクセスすることなので、次のアプローチを使用します。
!function() {
function ArrayND(size, N, fill) {
if (N < 1) throw new Error('Arrays must have at least one dimension.');
if (size < 1) throw new Error('Arrays must have at least one element.');
if (!(this instanceof ArrayND)) return new ArrayND(size, N, fill); // allow this ctor to be called without `new` operator
var arr = this;
arr.length = size;
populate(arr, 1);
function populate(a, depth) {
for (var i = 0; i < size; i++) {
if (depth < N) {
a[i] = new Array(size);
populate(a[i], depth+1);
} else a[i]=fill;
}
}
return arr;
}
var proto = Object.create(Array.prototype); // polyfill necessary for older browsers, see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create#Polyfill
proto.get = function(indicies) {
var pos = this;
for (var i = 0; i < indicies.length; i++) {
pos = pos[indicies[i]];
}
return pos;
};
proto.set = function(indicies, value) {
var pos = this;
for (var i = 0; i < indicies.length - 1; i++) {
pos = pos[indicies[i]];
}
pos[indicies[indicies.length-1]] = value;
}
ArrayND.prototype = proto;
this.ArrayND = ArrayND; // export to global scope
}();
これにより、両方の長所が得られます。 anew ArrayND(s, d)
は通常の配列のように見えて動作しますが、実行時に任意の数のインデックス引数を取ることができるアクセサーも提供します – すべて組み込みの を変更する必要はありませget
ん.set
Array
var arr = new ArrayND(5, 3, 'hi');
console.log(arr[0][1][2]); // => hi
console.log(arr.get([0,1,2]); // => hi
arr.push([]); // => 6 (the new length)
arr.set([6,0], 'I was added');