Array.prototype.filter() 的就地替代方法是什么

新手上路,请多包涵

我有一个数组,我想从中删除一些元素。我不能使用 Array.prototype.filter() ,因为我想就地修改数组(因为它节省了内存分配,而且对我来说更重要的是,它使代码在我的用例中更简单)。是否有我可以使用的 filter 的就地替代方案,也许类似于 Array.prototype.forEach() 可以用作 —17fdd654cb0f6c5ff3ff774-4- Array.prototype.map() 的就地变体

编辑:根据要求的最小示例:

 function someCallback(array) {
  // do some stuff
  array.filterInPlace(function(elem) {
    var result = /* some logic */
    return result;
  })
  // do some more stuff
}

原文由 Perseids 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 513
2 个回答

是否有就地替代过滤器

不,但是自己编写并不难。这是一种挤出所有不符合条件的值的方法。

 function filterInPlace(a, condition) {
  let i = 0, j = 0;

  while (i < a.length) {
    const val = a[i];
    if (condition(val, i, a)) a[j++] = val;
    i++;
  }

  a.length = j;
  return a;
}

condition 被设计为与传递给 Array#filter 的回调具有相同的签名,即 (value, index, array) 。为了与 Array#filter 完全兼容,您还可以接受第四个 thisArg 参数。

使用 forEach

使用 forEach 有一个小优点,它会跳过空槽。这个版本:

  • 压缩带有空槽的数组
  • 工具 thisArg
  • 跳过分配,如果我们还没有遇到失败的元素
 function filterInPlace(a, condition, thisArg) {
  let j = 0;

  a.forEach((e, i) => {
    if (condition.call(thisArg, e, i, a)) {
      if (i!==j) a[j] = e;
      j++;
    }
  });

  a.length = j;
  return a;
}

a = [ 1,, 3 ];
document.write('<br>[',a,']');

filterInPlace(a, x=>true);
document.write('<br>[',a,'] compaction when nothing changed');

b = [ 1,,3,,5 ];
document.write('<br>[',b,']');

filterInPlace(b, x=>x!==5);
document.write('<br>[',b,'] with 5 removed');

原文由 user663031 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以使用以下内容:

 array.splice(0, array.length,...array.filter(/*YOUR FUNCTION HERE*/))

解释:

  • 拼接动作到位
  • 第一个参数意味着我们从数组的开头开始
  • 第二种方法是删除整个数组
  • 第三种方法是我们用过滤后的副本替换它
  • … 是扩展运算符(仅限 ES6)并将数组的每个成员更改为单独的参数

原文由 Edward Kotarski 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题