JavaScript удалить массив из массива

Предположим, у нас есть следующие массивы:

a = [1, 2, 3, 4, 5]

а также

b = [2, 3]

Как я могу вычесть b из a? Итак, у нас есть c = a - b, который должен быть равен [1, 4, 5]. Решение jQuery также подойдет.


person David Weng    schedule 06.10.2011    source источник


Ответы (6)


Предположим, вы используете браузер с Array.prototype.filter и Array.prototype.indexOf, вы можете использовать это:

var c = a.filter(function(item) {
    return b.indexOf(item) === -1;
});

Если в рассматриваемом браузере нет этих методов, вы можете их скрыть.

person icktoofay    schedule 06.10.2011
comment
Кстати, IE8 — единственный подходящий браузер на рынке, который не реализует эти методы... Источник: kangax.github.com/es5-compat-table - person Šime Vidas; 06.10.2011
comment
@Какаши: Мне подходит. Какую версию ты используешь? - person icktoofay; 06.10.2011
comment
Обратите внимание, что приведенные выше ссылки содержат прокладки для filter и indexOf. - person Grinn; 16.09.2013

Это модифицированная версия ответа, опубликованного @icktoofay.

В ES6 мы можем использовать:

Это упростит наш код до:

var c = a.filter(x => !b.includes(x));

Демонстрация:

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var c = a.filter(x => !b.includes(x));
console.log(c);

person Mohammad Usman    schedule 18.01.2018

Для кода, который будет работать во всех браузерах, вам придется вручную найти каждый элемент из b в a и удалить его.

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var result = [], found;
for (var i = 0; i < a.length; i++) {
    found = false;
    // find a[i] in b
    for (var j = 0; j < b.length; j++) {
        if (a[i] == b[j]) {
            found = true;
            break;
        }
    }
    if (!found) {
        result.push(a[i]);
    }
}
// The array result now contains just the items from a that are not in b

Рабочий пример здесь: http://jsfiddle.net/jfriend00/xkBzR/

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

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

function filterArray(src, filt) {
    var temp = {}, i, result = [];
    // load contents of filt into object keys for faster lookup
    for (i = 0; i < filt.length; i++) {
        temp[filt[i]] = true;
    }

    // go through src
    for (i = 0; i < src.length; i++) {
        if (!(src[i] in temp)) {
            result.push(src[i]);
        }
    }
    return(result);
}

var filtered = filterArray(a, b);

Рабочий пример здесь: http://jsfiddle.net/jfriend00/LUcx6/

person jfriend00    schedule 06.10.2011
comment
почему бы не реализовать метод Array.filter? может быть полезен и в других случаях. - person Kakashi; 06.10.2011
comment
Array.filter() полезен - я просто предлагаю альтернативу. Некоторые люди не хотят добавлять методы к существующим базовым объектам или у них есть код, который может сломаться, если это будет сделано. - person jfriend00; 06.10.2011

Для тех, кто борется с объектами, такими как Date, вы обнаружите, что два разных объекта никогда не равны друг другу, даже если они имеют одинаковые значения, поэтому приведенные выше ответы не будут работать. Вот ответ на эту проблему в ES6.

const c = a.filter(aObject => b.findIndex(bObject => aObject.valueOf() === bObject.valueOf()) === -1)
person Nati Lara-Diaz    schedule 21.12.2017

Здесь реализация try работает во всех браузерах:

if('filter' in Array == false) {
    Array.prototype.filter = 
        function(callback) {
            if(null == this || void 0 == this) {
                return;
             }
            var filtered = [];
            for(i = 0, len = this.length; i < len; i++) {
                    var tmp = this[i];
                    if(callback(tmp)) {
                        filtered.push(tmp);
                     }
             }
                return filtered;
       }
  }

a = [1, 2, 3, 4, 5]; 
b = [2, 3]; 

var c = a.filter(function(item) { /*implementation of icktoofay */
    return b.indexOf(item) === -1;
});
person Kakashi    schedule 06.10.2011
comment
Array.indexOf также существует не во всех браузерах (например, ни в одной версии IE до IE9). - person jfriend00; 06.10.2011

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

let first = [1,2,3,4,5,6,7,9];
let second = [2,4,6,8];
const difference = first.filter(item=>!second.includes(item));
console.log(difference);//[ 1, 3, 6,7]
/*
the above will not work for objects with properties
This might do the trick
*/
const firstObj = [{a:1,b:2},{a:3,b:4},{a:5,b:6},{a:7,b:8}]//not ideal. I know
const secondObj = [{a:3,b:4},{a:7,b:8}]

const objDiff = firstObj.filter(obj=>
  !secondObj.find(sec=>//take note of the "!"
    sec.a===obj.a
    &&//or use || if you want to check for either or
    sec.b===obj.b
  )//this is formatted so that it is easily readable
);
console.log(objDiff)/*
[
  {
    "a": 1,
    "b": 2
  },
  {
    "a": 5,
    "b": 6
  }
]
*/

person Oluwaseyitan Baderinwa    schedule 15.06.2021