Javascript 算法在数组中查找不在另一个数组中的元素

我正在寻找一个好的算法,以获得一个数组中的所有元素,而不是另一个数组中的元素。给定这些数组:

var x = ["a","b","c","t"];
var ​​​​​​​​​y = [​​​​​​​"d","a","t","e","g"];

我想以这个数组结束:

var z = ["d","e","g"];

我使用的是 jquery,因此可以利用 $.each()$.inArray()。这是我想到的解决办法,但似乎应该有更好的办法。

// goal is to get rid of values in y if they exist in x
var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];


var z = [];
$.each(y, function(idx, value){
if ($.inArray(value,x) == -1) {
z.push(value);
}
});
​alert(z);  // should be ["d","e","g"]

这是 行动代码有什么想法吗?

79957 次浏览
var z = $.grep(y, function(el){return $.inArray(el, x) == -1});

Also, that method name is too short for its own good. I would expect it to mean isElementInArray, not indexOf.

For a demo with objects, see http://jsfiddle.net/xBDz3/6/

Make sorted copies of the arrays first. If the top elements are equal, remove them both. Otherwise remove the element that is less and add it to your result array. If one array is empty, then add the rest of the other array to the result and finish. You can iterate through the sorted arrays instead of removing elements.

// assume x and y are sorted
xi = 0; yi = 0; xc = x.length; yc = y.length;
while ( xi < xc && yi < yc ) {
if ( x[xi] == y[yi] ) {
xi += 1;
yi += 1;
} else if ( x[xi] < y[yi] ) {
z.push( x[xi] );
xi += 1;
} else {
z.push( y[yi] );
yi += 1;
}
}
// add remainder of x and y to z.  one or both will be empty.

Maybe jLinq can help you?

It lets you run queries like this against javascript objects.

For example:

var users = [ { name: "jacob", age: 25 },  { name: "bob" , age: 30 }]
var additionalusers = [ { name: "jacob", age: 25 },  { name: "bill" , age: 25 }]


var newusers = jLinq.from(users).except(additionalusers).select();


>>> newusers = [ { name: "bob" , age: 30 } ]

It's a bit overkill for you at the moment, but it's a robust solution that I was glad to learn about.

It can do intersects, unions, handle boolean logic and all kinds of great linq style goodness.

Here's an alternative using underscore.js:

function inAButNotInB(A, B) {
return _.filter(A, function (a) {
return !_.contains(B, a);
});
}

This is a late answer, but it uses no libraries so some may find it helpful.

/**
* Returns a non-destructive Array of elements that are not found in
* any of the parameter arrays.
*
* @param {...Array} var_args   Arrays to compare.
*/
Array.prototype.uniqueFrom = function() {
if (!arguments.length)
return [];
var a1 = this.slice(0); // Start with a copy


for (var n=0; n < arguments.length; n++) {
var a2 = arguments[n];
if (!(a2 instanceof Array))
throw new TypeError( 'argument ['+n+'] must be Array' );


for(var i=0; i<a2.length; i++) {
var index = a1.indexOf(a2[i]);
if (index > -1) {
a1.splice(index, 1);
}
}
}
return a1;
}

Example:

var sheetUsers = ['joe@example.com','fred@example.com','sam@example.com'];
var siteViewers = ['joe@example.com','fred@example.com','lucy@example.com'];
var viewersToAdd = sheetUsers.uniqueFrom(siteViewers);  // [sam@example.com]
var viewersToRemove = siteViewers.uniqueFrom(sheetUsers);  // [lucy@example.com]

Late answer with the new ECMA5 javascript:

var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];


myArray = y.filter( function( el ) {
return x.indexOf( el ) < 0;
});

in ES6 simply

const a1 = ["a", "b", "c", "t"];
const a2 = ["d", "a", "t", "e", "g"];


console.log( a2.filter(x => !a1.includes(x)) );

(another option is a2.filter(x => a1.indexOf(x)===-1) )

 findDiff = (A, B) => {
return  A.filter(function (a) {
return !B.includes(a);
});
}

I am quite late now but maybe it will be helpful for someone.

If the array is not just a simple array but an array of objects then the following can be used:

var arr1 = [
{
"prop1": "value1",
"prop2": "value2",
},
{
"prop1": "value3",
"prop2": "value4",
},
{
"prop1": "value5",
"prop2": "value6",
},
];


var arr2 = ['value1','value3', 'newValue'];


// finds all the elements of arr2 that are not in arr1
arr2.filter(
val => !arr1.find( arr1Obj => arr1Obj.prop1 === val)
); // outputs "newValue"