Başka bir dizide yer alan tüm öğeleri kaldır


222

Başka bir dizide mevcutlarsa bir javascript dizisinden tüm öğeleri kaldırmak için etkili bir yol arıyorum.

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

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

Bu durumda bırakmak için myArray üzerinde çalışmak istiyorum: ['a', 'd', 'e', 'f']

JQuery ile kullanıyorum grep()ve inArray()hangi iyi çalışır:

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

Döngü ve yapıştırma olmadan bunu yapmanın saf bir javascript yolu var mı?





Ne olursa olsun, her zaman belirli bir seviyede döngüyü içerecektir.
Mavi Gökyüzü

Gerçekten "verimli" olmasını istiyorsanız, gibi fonksiyonel tür yöntemleri kullanmayacaksınız .filter(). Bunun yerine fordöngüler kullanırsınız . .splice()Orijinal siparişin sürdürülmesi gerekmiyorsa kaçınabilirsiniz . Ya da .splice()kaldırılacak birçok öğe olacağını düşünüyorsanız daha verimli olmanın yolları vardır.
Mavi Gökyüzü

Yanıtlar:


379

Array.filter()Yöntemi kullanın :

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

Tarayıcı desteği Array.includes()arttıkça küçük iyileştirme :

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

Ok fonksiyonlarını kullanarak bir sonraki adaptasyon :

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );

23
OP: Eğer kullanıyorsanız Underscore.js var .difference()temelde yapar ki.
Bill Criswell

Tam da aradığım şey. Teşekkür ederim. @ BillCriswell, alt çizgilere bakacağım.
Musluk

1
Tüm unsurlarını dönüştürme @AlecRust toRemove()geri dönüşünde yer harf ve değişime elkarşı el.toUpperCase().
Sirko

5
veya daha kısa:myArray = myArray.filter( el => !toRemove.includes( el ) );
538ROMEO

1
bu sipariş n ^ 2 değil mi?
Frazer Kirkman

34

filterYöntem hile yapmak gerekir:

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

Senin Eğer toRemovedizi büyük, arama desen bu tür verimsiz olabilir. Bir harita oluşturmak daha performanslı olur, böylece arama yapmaktan O(1)ziyade olur 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]);

24

Bir nesne dizisi kullanıyorsanız. Daha sonra aşağıdaki kod, bir nesne özelliğinin yinelenen öğeleri kaldırma ölçütleri olacağı sihri yapmalıdır.

Aşağıdaki örnekte, her bir öğenin adı karşılaştırılarak kopyalar kaldırılmıştır.

Bu örneği deneyin. 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));



11

ECMAScript 6 setleri iki dizinin farklı elemanlarını hesaplamak için kullanılabilir:

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


8

Ben sadece olarak uyguladım:

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

Kullanım şekli:

myArray.exclude(toRemove);

1
prototypesYerli Nesneleri genişletmek iyi bir uygulama değildir Array. Bu, dilin gelecekteki gelişimi ile uzun vadeli bir çatışmaya neden olabilir ( davaya bakınflatten )
MarcoL

6

Yeni ES5 şeylerini kullanamıyorsanız filter, iki döngüye sıkıştığınızı düşünüyorum:

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

filter "new HTML5 stuff" değil
goofballLogic

"ES5" yazmalıydım. 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) ))

Bu kadar iyi karşılanmış bir soruya biraz açıklama eklemek ister misiniz, lütfen?
harmonica141

1
Sorun için saatlerce arama yaptım ve sadece buldum, sadece harika. Çok teşekkür ederim!
Tarvo Mäesepp

5

Şimdi tek katmanlı lezzette:

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

Eski tarayıcılarda çalışmayabilir.


3

Lodash'tan _.differenceBy'yi kullanabilirsiniz.

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

Burada örnek kod: CodePen


Öznitelik nesnenin içinde yuvalanmışsa ne olur? Sizin durumunuzda olduğu gibi bir şey testi {name: 'deepak', yer: 'bangalore', iç içe: {test: 1}}
Charith Jayasanka

2

Mümkün olan en basit:

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)


2
Unutmayın includesES7 önce kullanılamaz.
Greg

0

Başka bir dizide yer alan tüm öğeleri kaldırmanın uygun yolu, kaynak diziyi yalnızca öğeleri kaldırarak aynı nesneyi yapmaktır:

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

Veya CoffeeScript eşdeğeri:

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

Chrome geliştirme araçlarının içinde test etme:

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 ar1 = arr

19: 33: 20.317 ar1 === arr
19: 33: 20.331 doğru

19: 33: 43.592 arrremoveContained ([a, c])
19: 33: 52.433 arr === arr1
19: 33: 52.438 doğru

Açısal çerçeveyi kullanmak, koleksiyonları çok fazla izleyici ve yeniden yükleme yapmadan güncellediğinizde işaretçiyi kaynak nesneye tutmanın en iyi yoludur.


Bu cevap en iyi uygulamaları geçersiz kıldığı için kötüdür. Özellikle, sahip olmadığınız nesneleri asla değiştirmeyin. Bu durumda, büyük bir hayır-hayır olan Array nesnesini değiştirirsiniz.
Hibrit web geliştirici

0

Herhangi bir yerleşik yöntem kullanmadan mantığı oluşturuyorum, lütfen bana herhangi bir optimizasyon veya değişiklik bildirin. JS editöründe iyi çalıştığını test ettim.

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;
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.