稀疏数组的长度

3
我将有一个数组,将接收n个值,但这些值将在不同的时间添加到不同的索引中。但是,我需要在特定时间获取数组的长度。 案例1
var a = [1,2,3,3,4]

a.length //Returns 5 - OK

案例2
var a =[]
a[20] = 2
a.length //Returns 21 but I would like it to return 1

如何在情况2下将长度作为1获取?

唯一让它返回长度为1的方法是只有一个元素在其中... a[0] = 2 或者你是想让 length 返回具有值的元素数量? - Reinstate Monica Cellio
3
为什么你想把元素放在第20个位置?如果不是的话,你可以使用“push”来推入元素。 - S.Dan
@PraneshRavi:“我这么做是因为可能性存在”,听起来很奇怪! - Angel Politis
所以当你说 a[20]=2 时,你基本上是告诉它跳过前面的位置并将我的元素放在给定的位置。因此,长度应该返回更大的数字,不是吗?如果你仍然想通过使用自定义位置获得输出1,也许你可以编写一个循环遍历数组的函数? - S.Dan
@PraneshRavi 你能解释一下你想做什么吗?如果你只是想让.length返回数组中定义值的数量,那很简单,但实际上不清楚你想要什么。 - Reinstate Monica Cellio
9个回答

12

很多答案建议通过遍历数组或创建新数组然后计数(就像_.compact做的那样)。我认为这些都是错误的方法,因为使用.reduce可以使这个过程非常简单。

var arr = [];

arr[7] = 1;
arr[17] = 2
arr[33] = 0;
arr[9001] = 4

var count = arr.reduce(x => x+1, 0);

console.log(count);

只需一行19字节的代码就可以完成这项任务。这是因为.reduce不会遍历数组中的空位,所以它只会访问明确填充的索引。然后只需计算这些索引即可。

请注意,如果您在数组中有任何明确设置为undefined的索引,则它们仍将计入填充索引,如演示的那样。所以如果是这种情况,则需要在回调函数中进行相应的处理。

var arr = [];

arr[17] = 2
arr[42] = undefined

var count = arr.reduce(x => x+1, 0);
console.log(count);

var filteredCount = arr.reduce((x, value) => typeof value !== "undefined" ? x+1 : x, 0);
console.log(filteredCount);


1
也许这对提问者或其他人有帮助:Array.prototype.forEachArray.prototype.map实际上与Array.prototype.reduce具有相同的特性,即回调函数不会为空/未设置的元素调用。 - Chris K
非常好的解决方案,谢谢。我把你的代码部分添加到了我的答案中。如果有任何问题,请随时评论。 - Mykola Borysyuk

4

如果你能使用underscorelodash,你可以尝试这样做

var arrLen = _.compact(youArr).length;

如果您想使用纯JS,您需要编写一个简单的函数。该函数将计算不等于false的元素数量。
var len = 0;
arr.forEach(function(el){
  if (el) {count++;}
});
console.log(len);

如@vlaz所提到的,.reduce也可以起作用。

对于数字,我会使用Number.isInteger来获取数字计数,而不是typeof value !== "undefined"等方法。

如果您确定数组中的值始终为整数类型,则可以省略parseInt方法。

因此,在下面的示例中,使用parseInt = 4,不使用 = 3。

var arr = [];

arr[7] = 1;
arr[17] = null
arr[33] = 0;
arr[66] = undefined;
arr[77] = '7';
arr[99] = -7;
arr[9001] = false;


var count = arr.reduce((x, v) => Number.isInteger(parseInt(v)) ? x+1 : x, 0);

console.log(count);

希望这能帮到你。

1
你太棒了。我决定使用 lodash 而不是 underscore。谢谢! - Pranesh Ravi
如果值为falsey,例如0、false、undefined、null等,则此方法将失败。更好的测试方法是arr.forEach((v, i) => len += arr.hasOwnProperty(i)? 1 : 0)或者arr.reduce((a, v, i, arr)=> a+= arr..reduce((a, v, i, arr)=> a+= arr.hasOwnProperty(i)? 1 : 0, 0), 0) - RobG
@Vlaz已经在他的答案中提到了它。但我也会添加他的代码。这样人们就能更好地理解。 - Mykola Borysyuk

3
如果您需要计算未定义元素的数量:

var a = [];
a[20] = 2;

// count number of elements in a that are not undefined
var count = a.filter(x => typeof x !== 'undefined').length;

console.log(count); // prints 1


2
您可以计算数组的“键”(即填充的索引):
Object.keys(arr).length

0
你可以使用Array#forEach来计算项目数量。

forEach()按升序为数组中的每个元素执行提供的回调函数。它不会为已删除或未初始化(即在稀疏数组上)的索引属性调用。

var a = [1, 2, 3, 3, 4];

console.log(a.length); // 5
a[20] = 2;
console.log(a.length); // 21
var length = 0;
a.forEach(function () { length++; });
console.log(length); // 6


0
另一个一行代码的解决方案是使用{{link1:Filter}}。只需过滤掉真值(包括0),然后找到长度即可。即使将值明确设置为undefined或任何其他假值,此方法也适用。

var a =[]
a[20] = 2;
a[10] = undefined;
a[15] = 0;
var x = (a.filter(i=> i===0||!!i )).length;
console.log(x)


0

我认为这样的东西会满足你的需求,尽管不清楚为什么要将元素放到第20个位置。

function dynlength(array) {
    var length = 0;
    for (var i = 0; i < array.length; i++)
        if (array[i] !== undefined) length++;
    return length;
}

0

首先定义一个数组变量a=[];

要获取数组元素的数量,可以使用a.length。

当你执行a[20]='x';时,实际上数组被初始化为21个元素(第20个元素设置为你的值),并且记住21是你的数组中元素的数量。

如果你想要自定义值,可以尝试使用循环迭代。

var count=0;
for(var i=0;i<a.length;i++)
{
 if(a[i]!=undefined)
  {
    count++;
  }
}
console.log(count);

nullundefined 是两个不同的值。在索引0-19处的元素将是undefined,而不是null。 - Frxstrem
是的,我编辑了我的答案...只是尝试提供我的解决方案...下次我会确保不犯错误...感谢指出!:D - RohitS

0

使用arr.length属性将返回包括“空洞”在内的总长度。

您可以使用forEach()方法,该方法跳过数组中的空洞。

var arr1 = [];
var count = 0;

arr1[20] = 2;

alert(arr1.length);// this will always return including 'holes'

arr1.forEach(function(ele, i) { //this will skip the holes and will take real values into account
   count++;
});
alert(count);

您还可以检查每个索引中的“未定义”值并将其添加到计数变量中。但是在使用“未定义”来表示数组中的空“洞”时要小心。
您可以查看http://speakingjs.com/es5/ch18.html#array_holes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接