【问题标题】:JavaScript - more efficient way to truncate an arrayJavaScript - 截断数组的更有效方法
【发布时间】:2018-06-05 11:42:07
【问题描述】:

我有一个按升序排序的 int 数组,我想根据特定边界从尾部删除数组项。在我的情况下,截断数组的更好方法是什么?考虑下一个代码 sn-ps:

var a = [1, 2, 3, 4];
var length = a.length;
var boundary = 2;
var count = 0;
for (var i = length - 1; i >= 0; i--) {
    if (a[i] > boundary) {
        a[i] = null; // or delete a[i] ???
        count++;
    }
}
a.length -= count;

或相同但使用拼接

for (var i = length - 1; i >= 0; i--) {
    if (a[i] > boundary) {
        a.splice(i, 1);
    }
}

【问题讨论】:

  • 这两个sn-ps的代码做的事情非常不同,它们都没有删除只在尾部的元素。要了解我的意思,请使用 [4, 3, 2, 1] 作为您的数组。
  • 我的数组总是升序排列。
  • 啊,我没注意到那个细节。那么你应该使用二进制搜索。
  • 好点!没想到,但需要试一试!

标签: javascript arrays algorithm


【解决方案1】:
 a.length -= count;

这就够了;)(因为长度不是一个简单的属性,而是一个截断/添加元素(ref)的getter/setter)

或者使用拼接:

 a.splice(-count, count);

【讨论】:

  • 你能解释一下为什么吗?幕后发生了什么?
  • @Alex 可能类似于splice(),但它不需要创建一个已移除元素的数组,也无需担心拼接后的元素移动。
  • 如果我正确解释了 OP 的问题,他想删除 x 尾部元素,它们是 > boundary,而不是特别是 #count 元素。 count 只是他用来跟踪在第一个 sn-p 中 > boundary 有多少元素的变量。 a.length -= count; 已经完全是他在那个样本中所做的,一旦他确定了要删除的元素的数量,但这还不知道。
  • @Paulpro 你说得对,count 是一种跟踪我想从尾部切掉的元素数量的方法。
  • @paulpro imo 真正的问题是a[i] = null; // or delete a[i] ??? 我在上面回答了
【解决方案2】:

在现代引擎中,或使用垫片,您可以使用Array.prototype.findIndex

var a = [1, 2, 3, 4];
var boundary = 2;
a.length = a.findIndex( x => x > boundary );
console.log( a );

由于您的数组已排序,您也可以使用Array.prototype.filter

var a = [1, 2, 3, 4];
var boundary = 2;
a = a.filter( x => x <= boundary );
console.log( a );

如果数组很大,可能会稍微慢一些(可以忽略不计),但在旧引擎中支持更多。

【讨论】:

    【解决方案3】:

    不要删除数组末尾的数组条目以截断它。删除数组条目通过创建稀疏数组将它们从数组中删除:数组的length 属性保持不变:

    var a = [1,2,3,4];
    console.log( "a.length %s", a.length);
    delete a[3];
    console.log( "a[3] after deletion: %s", a[3]);
    console.log( "a.length after deletion %s", a.length);
    console.log( "a[3] still exists: %s", a.hasOwnProperty("3"));

    类似的考虑适用于将数组条目设置为null。它们将不再在条件表达式中测试为真,但尚未被删除。和以前一样,数组的长度将保持不变。

    将数组的长度设置为比其现有值短的值会在原地截断它。有许多方法可以找到截断数组的边界位置。我建议选择一种对您来说看起来很自然并且可以在目标浏览器中使用的。例如。在排序数组上使用forSome 可能不符合您的要求:)

    var a = [1,2,3,4];
    var boundary = 2;
    a.some(
       (c,i) => {
          if( c > boundary)
          {  a.length = i;
             return true;
          }
       }
    );
    
    console.log( a)

    如果使用splice,请注意从边界位置到数组末尾的所有条目都可以在一次调用中删除,而不是一次删除一个:

    var a = [1,2,3,4];
    var boundary = 2;
    for( var i = a.length-1; a[i]>boundary; --i) {} // linear search
    a.splice(i+1);
    console.log(a);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-06
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2011-02-21
      • 2018-03-12
      相关资源
      最近更新 更多