从数组中删除末尾等于零的元素 - 更好的方法

7

我有一个包含数字的非常长的数组。我需要从该数组中删除尾随的零。

如果我的数组看起来像这样:

var arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

我希望移除除了[1, 2, 0, 1, 0, 1]之外的所有内容。

我已经创建了一个能够达到预期效果的函数,但我想知道是否有内置函数可以使用。

var arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
for(i=arr.length-1;i>=0;i--)
{
    if(arr[i]==0) 
    {
        arr.pop();
    } else {
        break;
    }
}
console.log(arr);

这个能否更好、更快地完成?

6个回答

17

假设:

var arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

您可以使用这段更短的代码:

while(arr[arr.length-1] === 0){ // While the last element is a 0,
    arr.pop();                  // Remove that last element
}

结果:

arr == [1,2,0,1,0,1]

@frieder:嗯,不是这样的。(false == 0) === false - Cerbrus
1
@Cerbrus 我之前关于 null 的说法是错误的,但是 false == 0 会返回 true,而 false === 0 则会返回 false。我刚刚测试过了:http://postimg.org/image/dltqr0799/ - Friedrich
@frieder:我明白了。已编辑帖子。 - Cerbrus
空数组会导致程序出错。 - kofifus
@kofifus:不会的。var arr = []; while(arr[arr.length-1]){console.log('foo')} 完全没问题。它不会抛出任何错误。 - Cerbrus
显示剩余3条评论

2
var arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

var copy = arr.slice(0);
var len = Number(copy.reverse().join('')).toString().length;
arr.length = len;

arr -> [1, 2, 0, 1, 0, 1]

如何运作

copy.reverse().join('') 变成了 "00000000000000000101021"

当你将一个数字字符串转换为数字时,所有前导零都会被删除。

var len  = Number(copy.reverse().join('')) becomes 101021

现在只需计算数字,我就知道从哪里删除尾随的零,并且最快删除尾随元素的方法是通过重置数组的长度。

arr.length = len;

DEMO


我刚刚看了这个答案,必须说它非常有趣。我从未想过以这种方式去除尾随零。我已经使用了@Cerbrus的答案,但我会尝试比较这两种方法的性能。很遗憾我们不能将多个答案标记为正确。 - Misiu

1
const arr = [0,0,0,1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

我的解决方案是:

arr.join('').replace(/0+$/g,'').split('').map(Number);

它将删除给定数组中的尾随零。
Result is [0,0,0,1,2,0,1,0,1];

如果您还需要删除前导零,您可以按照以下方式调整正则表达式:

arr.join('').replace(/^0+|0+$/g,'').split('').map(Number);

现在它不仅会删除尾部零,还会删除前导零

Result is [1,2,0,1,0,1];

这将从数组的开头和结尾删除零。我需要一种方法来删除“尾随”零。 - Misiu
是的,我提供了更通用的解决方案。如果您只想修剪尾随零,则在正则表达式中删除前导零即可。以这种方式 arr.join('').replace(/0+$/g,'').split('').map(Number); - denelvis

0

这是一个单行代码,代表了 JavaScript 的最佳和最差的两面性。

var arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

arr.slice(0,arr.reduceRight(([d,l],c) => [d||c,l-!(d||c)], [false,arr.length])[1])

输出:

[ 1, 2, 0, 1, 0, 1 ]

slice的需求是什么?arr.reduceRight((acc, item) => { if(item === 0 && acc.length === 0) { return acc; } return acc.concat(item); }, []);这个也可以工作。 - Rahul.A.Krishna

0
使用reduceRight的更简单的不可变方法
const arr = [1,2,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

const prunedArray = arr.reduceRight((acc, item) => {
  if(item === 0 && acc.length === 0) {
    return acc;
  }
  return acc.concat(item);
}, []);

console.log(prunedArray); // [1, 0, 1, 0, 2, 1]


0

已接受的答案非常好。只是为了好玩,这里提供一种简化的方法。

var a = [1,0,1,0,1,0,1,2,3,4,5,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0];
    f = a => { var b = true;
               return a.reduceRight((r,n,i) => ( b ? n && ( b = false
                                                          , r[i] = n
                                                          )
                                                   : r[i] = n
                                               , r
                                               )         
                                   , []
                                   );
             };
console.log(f(a));


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