我知道JavaScript中的数组与传统数组不同,因为它们只是引擎盖下的对象。因此,在内存管理方面,JavaScript允许稀疏数组以类似于密集数组的方式运行。使用稀疏数组时,有没有办法有效地到达该数组中的下一个元素?
例如,给定此数组:
var foo = [];
foo[0] = '0';
foo[1] = '1';
foo[2] = '2';
foo[100] = '100';
console.log(foo.length); // => 101
我知道有一种方法可以使用for ... in
来获取所有元素:
for (var n in foo){
console.log(n);
}
// Output:
// 0
// 1
// 2
// 100
但是,是否有一种明确的方法可以简单地从其中一个元素到另一个元素?
例如,是否存在某种实现类似行为的方法?
var curElement = foo[2]; // => 2 (the contents of foo[2])
var nextElement = curElement.next(); // => 100 (the contents of foo[100])
// ^^^^^^
// Not an actual function, but does there exist some way to potentially
// mimic this type of behavior efficiently?
答案 0 :(得分:3)
您可以创建自己的SparseArray
类型,其中包含所有Array方法,但维护一个单独的索引列表以进行迭代,以便您可以有效地跳过漏洞。
这是这种类型的开始。它允许您迭代,推送,添加特定索引,获取/检查特定索引。
还添加了.toString()
以供显示。
未完全测试,因此可能存在错误。您需要根据需要添加功能。
function SparseArray(arr) {
this.data = arr || [];
this.indices = [];
for (var i = 0; i < this.data.length; i++) {
if (this.data.hasOwnProperty(i)) {
this.indices.push(i);
}
}
}
SparseArray.prototype.forEach = function(cb, thisArg) {
for (var i = 0; i < this.indices.length; i++) {
cb.call(thisArg, this.data[this.indices[i]], i, this);
}
};
SparseArray.prototype.push = function(item) {
this.indices.push(this.data.push(item) - 1);
};
SparseArray.prototype.addAt = function(idx, item) {
if (idx >= this.data.length) {
this.indices.push(idx);
} else if (!(idx in this.data)) {
for (var i = 0; i < this.indices.length; i++) {
if (this.indices[i] >= idx) {
this.indices.splice(i, 0, idx);
break;
}
}
}
this.data[idx] = item;
};
SparseArray.prototype.hasIndex = function(idx) {
return idx in this.data;
};
SparseArray.prototype.getIndex = function(idx) {
return this.data[idx];
};
SparseArray.prototype.nextFrom = function(idx) {
for (var i = 0; i < this.indices.length; i++) {
if (this.indices[i] >= idx) {
return this.data[this.indices[i]];
}
}
};
SparseArray.prototype.toString = function() {
var res = [];
this.forEach(function(item) {
res.push(item);
});
return res.join(", ");
};
var foo = [];
foo[0] = '0';
foo[1] = '1';
foo[2] = '2';
foo[100] = '100';
var pre = document.querySelector("pre");
var sa = new SparseArray(foo);
pre.textContent += "Start\n" + sa + "\n\n";
sa.addAt(1000, "1000");
pre.textContent += "Adding 1000\n" + sa + "\n\n";
sa.push("1001");
pre.textContent += "Pushing 1001\n" + sa + "\n\n";
pre.textContent += "Next from 300 is: " + sa.nextFrom(300) + "\n\n";
<pre></pre>
答案 1 :(得分:1)
正如上面评论中提到的斜视,我会做的一种方法涉及另一个数组。您可以跟踪实际上对您有意义的索引,这样您就可以直接跳转到这些索引。但是,我有另一个想法。
如果要消除大量开销,可以保留一个您关心的值数组,以及它们对应的一个索引数组。 (请注意,这更像是Map - Java中的数据结构)。这样,您可以迭代所需的数字,并在另一个数组中获得所需的索引。
Array 1: 1, 3, 6, 8
Array 2: 234, 298, 400, 500
因此值1出现在数据的索引234处,值3出现在298 ...
我认为这将大大提高大型数据集和小型数据集的性能。但是,我不完全确定javascript中的查找是如何工作的。
答案 2 :(得分:-1)
尝试使用.slice()
,.filter()
// slice index of `curElement` + 1 through `foo` `.length`
var curr = foo.slice(foo.indexOf(curElement) + 1, foo.length);
// if `val` defined , return `val`
// alternatively , `return val !== undefined || val !== null`
var next = curr.filter(function(val) { return val })[0];
var foo = [];
foo[0] = '0';
foo[1] = '1';
foo[2] = '2';
foo[100] = '100';
var curElement = foo[2]; // => 2 (the contents of foo[2])
var curr = foo.slice(foo.indexOf(curElement) + 1, foo.length);
var next = curr.filter(function(val) { return val})[0];
console.log(next)
&#13;
或者,可以使用while
循环
var foo = [];
foo[0] = '0';
foo[1] = '1';
foo[2] = '2';
foo[100] = '100';
var n = 2, next;
var curElement = foo[n]; // => 2 (the contents of foo[2])
while (n < foo.length) {
if (foo[++n] !== undefined) {next = foo[n]; break;}
}
console.log(next)
&#13;