Алгоритм Javascript для поиска элементов в массиве, которых нет в другом массиве - PullRequest
25 голосов
/ 03 июня 2010

Я ищу хороший алгоритм, чтобы получить все элементы в одном массиве, которые не являются элементами в другом массиве. Итак, учитывая эти массивы:

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"]

Вот код в действии . Есть идеи?

Ответы [ 7 ]

50 голосов
/ 17 февраля 2014

Поздний ответ с новым 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;
});
18 голосов
/ 05 июля 2017

в ES6 просто

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

console.log( y.filter(e => !x.includes(e)) );

(другой вариант y.filter(e => x.indexOf(e)===-1))

12 голосов
/ 24 апреля 2013

Вот альтернативный вариант использования underscore.js :

function inAButNotInB(A, B) {
  return _.filter(A, function (a) {
    return !_.contains(B, a);
  });
}
12 голосов
/ 03 июня 2010
var z = $.grep(y, function(el){return $.inArray(el, x) == -1}); 

Кроме того, имя этого метода слишком короткое для собственного блага. Я ожидаю, что это будет означать isElementInArray, а не indexOf.

Демонстрацию с объектами см. http://jsfiddle.net/xBDz3/6/

2 голосов
/ 09 января 2014

Это поздний ответ, но он не использует библиотеки, поэтому некоторые могут найти его полезным.

/**
 * 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;
}

Пример:

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]
2 голосов
/ 03 июня 2010

Может быть, jLinq может вам помочь?

Позволяет запускать подобные запросы к объектам javascript.

Например:

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 } ]

В настоящий момент это немного излишне, но это надежное решение, о котором я был рад узнать.

Он может выполнять пересечения, объединения, обрабатывать булеву логику и все виды великих добра в стиле linq.

2 голосов
/ 03 июня 2010

Сначала создайте отсортированные копии массивов. Если верхние элементы равны, удалите их обоих. В противном случае удалите элемент, который меньше, и добавьте его в массив результатов. Если один массив пуст, добавьте остаток от другого массива к результату и завершите. Вы можете перебирать отсортированные массивы вместо удаления элементов.

// 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...