What is the in-place alternative to Array.prototype.filter()

后端 未结 6 1261
面向向阳花
面向向阳花 2020-11-29 07:37

I\'ve got an array that I would like to remove some elements from. I can\'t use Array.prototype.filter(), because I want to modify the array in place (because i

6条回答
  •  情深已故
    2020-11-29 08:08

    Is there an in-place alternative to filter

    No, but it's not hard to write your own. Here is an approach which squeezes out all the values which fail a condition.

    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 is designed to have the same signature as the callback passed to Array#filter, namely (value, index, array). For complete compatibility with Array#filter, you could also accept a fourth thisArg parameter.

    Using forEach

    Using forEach has the minor advantage that it will skip empty slots. This version:

    • Compacts arrays with empty slots
    • Implements thisArg
    • Skipps the assignment, if we have not yet encountered a failing element

    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('
    [',a,']'); filterInPlace(a, x=>true); document.write('
    [',a,'] compaction when nothing changed'); b = [ 1,,3,,5 ]; document.write('
    [',b,']'); filterInPlace(b, x=>x!==5); document.write('
    [',b,'] with 5 removed');

提交回复
热议问题