简体   繁体   English

JavaScript数组:拼接和过滤器之间是否有交叉的方法?

[英]JavaScript array: is there a method that is a cross between splice and filter?

I have an array of objects, and want to: 我有一组对象,并且想要:

  1. Remove certain objects from the array 从阵列中删除某些对象
  2. Treat the removed objects in a second step 第二步处理已移除的对象

I don't know in advance where these objects are. 我事先不知道这些对象在哪里。 To recognize them, I need to use a function that queries their properties. 为了识别它们,我需要使用一个查询其属性的函数。 It makes sense to retrieve the removed objects in a second array. 在第二个数组中检索删除的对象很有意义。

I had hoped to find a native method like filter or splice that would do this. 我曾希望找到一个可以执行此操作的本机方法,例如filtersplice Here's what I've come up with as a solution: 这是我想出的解决方案:

if (!Array.prototype.cherrypick) {
  Array.prototype.cherrypick = function(fn) {
    let basket = []
    let ii = this.length
    let item

    for ( ; ii-- ; ) {
      item = this[ii]

      if (fn(item)) {
        basket.unshift(item)
        this.splice(ii, 1)
      }
    }

    return basket
  }
}

Have I missed something? 我错过了什么吗? Is there a native method that does this already? 是否已有本机方法? Is my solution unsound in some way? 我的解决方案有些不完善吗?

Methods such as Array.filter() returns a new array instead of changing the original array. 诸如Array.filter()返回一个新数组,而不是更改原始数组。

You can create a partition method using Array.reduce() that will return two arrays - those that passed the predicate, and those that failed: 您可以使用Array.reduce()创建一个分区方法,该方法将返回两个数组-那些通过谓词的数组和那些失败的数组:

 const partition = (predicate, arr) => arr.reduce((r, o) => { r[+!!predicate(o)].push(o); return r; }, [[], []]); const arr = [4, 8, 3, 10, 12]; const result = partition(n => n > 5, arr); console.log(result); 

And you can use the partition logic with Array.splice() to create the cherrypick method: 您可以将分区逻辑与Array.splice()来创建cherrypick方法:

 if (!Array.prototype.cherrypick) { Array.prototype.cherrypick = function(predicate) { const [removedItems, items] = arr.reduce((r, o) => { r[+!!predicate(o)].push(o); return r; }, [[], []]); this.splice(0, arr.length, items); return removedItems; } } const arr = [4, 8, 3, 10, 12]; const removed = arr.cherrypick(n => n > 5); console.log('arr ', arr); console.log('removed ', removed); 

Have I missed something? 我错过了什么吗? Is there a native method that does this already? 是否已有本机方法?

No, most native utility methods try not to mutate the array and instead return a new one. 不,大多数本机实用程序方法都尝试不改变数组,而是返回一个新数组。

Is my solution unsound in some way? 我的解决方案有些不完善吗?

Using splice and unshift repeatedly like you do is very inefficient. 像您一样反复使用spliceunshift非常低效。 Better write 更好的写

if (typeof Array.prototype.cherrypick == "function")
  console.warn("something already defines Array#cherrypick!");
Array.prototype.cherrypick = function(predicate) {
  let removed = [];
  for (let i=0, j=0; i<this.length; i++) {
    const item = this[i];
    if (fn(item)) {
      removed.push(item);
    } else {
      this[j++] = item; // keep in array, but at new position
    }
  }
  this.length = j; // removes rest
  return removed;
};

Just filter twice: 只需过滤两次:

const picked = array.filter(fn);
array = array.filter((el, i, a) => !fn(el, i, a));

Use reduce as follows : 如下使用reduce:

  array = [1,2,3,4,5,6,7];
  fn = n => n % 3 == 0;
  [array, picked] = array.reduce ( (r, el) => (r[+fn(el)].push (el), r), [[], []] ) 

Do you want something like this? 你想要这样的东西吗?

const basket = ['apple', 'banana', 'car'];
const filterMapBasket = basket
                       .filter(item => item !== 'car')
                       .map(item => {return { name: item }});

This will result the initial basket array of strings to be filtered and transformed to an array of objects. 这将导致初始的篮子字符串数组被过滤并转换为对象数组。

This will alter the source array in place removing items meeting some test, and return those items... 这将改变源数组的位置,删除满足某些测试条件的项目,然后返回这些项目...

 Array.prototype.removeIf = function(fn) { let i = this.length; let removed = []; while (i--) { if (fn(this[i], i)) { removed.push(...this.splice(i, 1)); } } return removed; }; let a = [0,1,2,3,4,5]; let removed = a.removeIf(i => i%2); console.log(a); console.log(removed); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM