我正在寻找一种有效的方法,从javascript数组中删除所有元素,如果它们存在于另一个数组中。
// If I have this array:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
// and this one:
var toRemove = ['b', 'c', 'g'];
我想对myArray进行操作,使其处于这种状态:['a', 'd', 'e', 'f']
与jQuery,我使用grep()和inArray(),这工作得很好:
myArray = $.grep(myArray, function(value) {
return $.inArray(value, toRemove) < 0;
});
有没有一个纯javascript的方法来做到这一点没有循环和剪接?
删除另一个数组中包含的所有元素的正确方法是通过只删除元素来使源数组成为相同的对象:
Array.prototype.removeContained = function(array) {
var i, results;
i = this.length;
results = [];
while (i--) {
if (array.indexOf(this[i]) !== -1) {
results.push(this.splice(i, 1));
}
}
return results;
};
或CoffeeScript等价:
Array.prototype.removeContained = (array) ->
i = @length
@splice i, 1 while i-- when array.indexOf(@[i]) isnt -1
在chrome开发工具内测试:
19:33:04.447 = 1
19:33:06.354 b = 2
19:33:07.615 c = 3
19:33:09.981 arr = [a,b,c]
19:33:16.460 arr1 = arr
19:33:20.317 arr1 === arr
19:33:20.331真实
19:33:43.592 arr.removeContained ([c])
19:33:52.433 arr === arr1
19:33:52.438真实
使用Angular框架是在更新集合时保持指针指向源对象的最佳方法,而不需要大量的监视器和重载。
如果您正在使用对象数组。然后,下面的代码将发挥神奇的作用,其中对象属性将作为删除重复项的标准。
在下面的示例中,比较每个项目的名称,已删除重复项。
试试这个例子。http://jsfiddle.net/deepak7641/zLj133rh/
var myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'chirag', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chandan', place: 'mumbai'}
];
var toRemove = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'}
];
for( var i=myArray.length - 1; i>=0; i--){
for( var j=0; j<toRemove.length; j++){
if(myArray[i] && (myArray[i].name === toRemove[j].name)){
myArray.splice(i, 1);
}
}
}
alert(JSON.stringify(myArray));
我没有使用任何内置方法构建逻辑,请让我知道任何优化或修改。
我在JS编辑器中测试了,它工作得很好。
var myArray = [
{name: 'deepak', place: 'bangalore'},
{name: 'alok', place: 'berhampur'},
{name: 'chirag', place: 'bangalore'},
{name: 'chandan', place: 'mumbai'},
];
var toRemove = [
{name: 'chirag', place: 'bangalore'},
{name: 'deepak', place: 'bangalore'},
/*{name: 'chandan', place: 'mumbai'},*/
/*{name: 'alok', place: 'berhampur'},*/
];
var tempArr = [];
for( var i=0 ; i < myArray.length; i++){
for( var j=0; j<toRemove.length; j++){
var toRemoveObj = toRemove[j];
if(myArray[i] && (myArray[i].name === toRemove[j].name)) {
break;
}else if(myArray[i] && (myArray[i].name !== toRemove[j].name)){
var fnd = isExists(tempArr,myArray[i]);
if(!fnd){
var idx = getIdex(toRemove,myArray[i])
if (idx === -1){
tempArr.push(myArray[i]);
}
}
}
}
}
function isExists(source,item){
var isFound = false;
for( var i=0 ; i < source.length; i++){
var obj = source[i];
if(item && obj && obj.name === item.name){
isFound = true;
break;
}
}
return isFound;
}
function getIdex(toRemove,item){
var idex = -1;
for( var i=0 ; i < toRemove.length; i++){
var rObj =toRemove[i];
if(rObj && item && rObj.name === item.name){
idex=i;
break;
}
}
return idex;
}
过滤方法应该做到这一点:
const myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const toRemove = ['b', 'c', 'g'];
// ES5 syntax
const filteredArray = myArray.filter(function(x) {
return toRemove.indexOf(x) < 0;
});
如果toRemove数组很大,这种查找模式可能效率很低。创建一个映射,使查找是O(1)而不是O(n),这样会更有性能。
const toRemoveMap = toRemove.reduce(
function(memo, item) {
memo[item] = memo[item] || true;
return memo;
},
{} // initialize an empty object
);
const filteredArray = myArray.filter(function (x) {
return toRemoveMap[x];
});
// or, if you want to use ES6-style arrow syntax:
const toRemoveMap = toRemove.reduce((memo, item) => ({
...memo,
[item]: true
}), {});
const filteredArray = myArray.filter(x => toRemoveMap[x]);