Hapus semua elemen yang ada di array lain

222

Saya mencari cara yang efisien untuk menghapus semua elemen dari array javascript jika mereka ada di array lain.

// If I have this array:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

// and this one:
var toRemove = ['b', 'c', 'g'];

Saya ingin beroperasi di myArray agar tetap seperti ini: ['a', 'd', 'e', 'f']

Dengan jQuery, saya menggunakan grep()dan inArray(), yang berfungsi dengan baik:

myArray = $.grep(myArray, function(value) {
    return $.inArray(value, toRemove) < 0;
});

Apakah ada cara javascript murni untuk melakukan ini tanpa perulangan dan splicing?

Keran
sumber
1
mungkin duplikat Hapus elemen tertentu dari array?
mplungjan
4
kemungkinan duplikat perbedaan larik JavaScript
Explosion Pills
1
kemungkinan duplikat Bisakah Anda menghapus satu array dari yang lain dalam javascript atau jquery - Anda tidak bisa terlalu memperhatikan saran yang dibuat ketika Anda menulis pertanyaan
mplungjan
Tidak peduli apa, itu akan selalu melibatkan pengulangan pada tingkat tertentu.
Blue Skies
Jika Anda benar-benar ingin menjadi "efisien", Anda tidak akan menggunakan metode tipe fungsional seperti .filter(). Sebagai gantinya Anda akan menggunakan forloop. Anda dapat menghindari .splice()jika pesanan asli tidak perlu dipertahankan. Atau ada cara untuk membuat .splice()lebih efisien jika Anda berpikir akan ada banyak item untuk dihapus.
Blue Skies

Jawaban:

379

Gunakan Array.filter()metode:

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

Peningkatan kecil, karena dukungan browser untuk Array.includes()telah meningkat:

myArray = myArray.filter( function( el ) {
  return !toRemove.includes( el );
} );

Adaptasi berikutnya menggunakan fungsi panah :

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );
Sirko
sumber
23
OP: Jika Anda menggunakan Underscore.js ada .difference()yang pada dasarnya melakukan ini.
Bill Criswell
Apa yang saya cari. Terima kasih. @ BillCriswell, saya akan memeriksa garis bawah.
Ketuk
1
@AlecRust Konversi semua elemen toRemove()ke huruf besar dan ubah panggilan balik dari elmenjadi el.toUpperCase().
Sirko
5
atau lebih pendek:myArray = myArray.filter( el => !toRemove.includes( el ) );
538ROMEO
1
bukankah urutan ini n ^ 2?
Frazer Kirkman
34

The filterMetode harus melakukan trik:

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;
});

Jika toRemovearray Anda besar, pola pencarian semacam ini bisa jadi tidak efisien. Akan lebih berkinerja untuk membuat peta sehingga pencarian O(1)lebih daripada 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]);
Ashwin Balamohan
sumber
24

Jika Anda menggunakan berbagai objek. Maka kode di bawah ini harus melakukan keajaiban, di mana properti objek akan menjadi kriteria untuk menghapus item duplikat.

Dalam contoh di bawah ini, duplikat telah dihapus dengan membandingkan nama setiap item.

Coba contoh ini. 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));

Deepak Acharya
sumber
11

ECMAScript 6 set dapat digunakan untuk menghitung elemen yang berbeda dari dua array:

const myArray = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g']);
const toRemove = new Set(['b', 'c', 'g']);

const difference = new Set([...myArray].filter((x) => !toRemove.has(x)));

console.log(Array.from(difference)); // ["a", "d", "e", "f"]

Benny Neugebauer
sumber
8

Saya baru saja menerapkan sebagai:

Array.prototype.exclude = function(list){
        return this.filter(function(el){return list.indexOf(el)<0;})
}

Digunakan sebagai:

myArray.exclude(toRemove);
pengguna2582833
sumber
1
Ini bukan praktik yang baik untuk memperluas prototypesObjek asli, seperti itu Array. Itu bisa memiliki konflik jangka panjang dengan perkembangan bahasa di masa depan ( lihat flattenkasusnya )
Marco
6

Jika Anda tidak dapat menggunakan hal-hal ES5 baru seperti itu filtersaya pikir Anda terjebak dengan dua loop:

for( var i =myArray.length - 1; i>=0; i--){
  for( var j=0; j<toRemove.length; j++){
    if(myArray[i] === toRemove[j]){
      myArray.splice(i, 1);
    }
  }
}
MarcoL
sumber
filter bukan "hal HTML5 baru"
goofballLogic
Saya seharusnya menulis "ES5 stuff". Itu tidak tersedia dengan ES3
MarcoL
6
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'}
];



myArray = myArray.filter(ar => !toRemove.find(rm => (rm.name === ar.name && ar.place === rm.place) ))
mojtaba roohi
sumber
Maukah Anda menambahkan beberapa penjelasan tentang pertanyaan yang diterima dengan baik itu?
harmonika141
1
Saya mencari solusi untuk masalah itu dan baru saja menemukannya, sangat mengagumkan. Terima kasih banyak!
Tarvo Mäesepp
5

Sekarang dalam rasa one-liner:

console.log(['a', 'b', 'c', 'd', 'e', 'f', 'g'].filter(x => !~['b', 'c', 'g'].indexOf(x)))

Mungkin tidak berfungsi di browser lama.

Matas Vaitkevicius
sumber
3

Anda dapat menggunakan _.differenceBy dari lodash

const myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
const toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];
const sorted = _.differenceBy(myArray, toRemove, 'name');

Contoh kode di sini: CodePen

Craciun Ciprian
sumber
Bagaimana jika atribut bersarang di dalam objek? Tes sesuatu seperti dalam kasus Anda {name: 'deepak', tempat: 'bangalore', bersarang: {test: 1}}
Charith Jayasanka
2

Bagaimana dengan yang paling sederhana:

var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var toRemove = ['b', 'c', 'g'];

var myArray = myArray.filter((item) => !toRemove.includes(item));
console.log(myArray)

Eggon
sumber
2
Ingatlah bahwa includesitu tidak tersedia sebelum ES7.
Greg
0

Cara yang tepat untuk menghapus semua elemen yang terdapat dalam array lain adalah dengan membuat array sumber objek yang sama dengan menghapus hanya elemen:

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

Atau yang setara dengan CoffeeScript:

Array.prototype.removeContained = (array) ->
  i = @length
  @splice i, 1 while i-- when array.indexOf(@[i]) isnt -1

Pengujian di dalam alat dev krom:

19: 33: 04.447 a = 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 benar

19: 33: 43.592 arr.removeContained ([a, c])
19: 33: 52.433 arr === arr1
19: 33: 52.438 true

Menggunakan kerangka kerja Angular adalah cara terbaik untuk menjaga pointer ke objek sumber saat Anda memperbarui koleksi tanpa jumlah besar pengamat dan memuat ulang.

Михаил Юдин
sumber
Jawaban ini buruk karena membatalkan praktik terbaik. Secara khusus, jangan pernah memodifikasi objek yang tidak Anda miliki. Dalam hal ini, Anda memodifikasi objek Array, yang merupakan no-no besar.
Web hybrid dev
0

Saya membangun logika tanpa menggunakan metode bawaan, beri tahu saya optimasi atau modifikasi apa pun. Saya diuji dalam editor JS itu berfungsi dengan baik.

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;
        }
Shravan R
sumber