我有一个对象数组,并且想要:
我事先不知道这些物体在哪里。为了识别它们,我需要使用一个查询其属性的函数。在第二个数组中检索已删除的对象很有意义。
我曾经希望找到一种可以执行此操作的本机方法,例如filter
或splice
。这是我想出的解决方案:
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
}
}
我错过了什么吗?是否已有本机方法?我的解决方案在某种程度上不正确吗?
答案 0 :(得分:1)
诸如Array.filter()
之类的方法将返回一个新数组,而不是更改原始数组。
您可以使用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);
您可以将分区逻辑与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);
答案 1 :(得分:1)
我错过了什么吗?是否已有本机方法?
否,大多数本机实用程序方法都尽量不对数组进行突变,而是返回一个新数组。
我的解决方案听起来有些奇怪吗?
像您一样反复使用splice
和unshift
效率很低。写得更好
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;
};
答案 2 :(得分:0)
只需过滤两次:
const picked = array.filter(fn);
array = array.filter((el, i, a) => !fn(el, i, a));
答案 3 :(得分:0)
按如下方式使用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), [[], []] )
答案 4 :(得分:0)
您想要这样的东西吗?
const basket = ['apple', 'banana', 'car'];
const filterMapBasket = basket
.filter(item => item !== 'car')
.map(item => {return { name: item }});
这将导致初始的一篮子字符串数组被过滤并转换为对象数组。
答案 5 :(得分:0)
这将改变源数组的位置,删除满足某些测试条件的项目,并返回这些项目...
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);