web-dev-qa-db-fra.com

Comment supprimer un élément d'un tableau dans une boucle forEach?

J'essaie de supprimer un élément d'un tableau dans une boucle forEach, mais j'ai des problèmes avec les solutions standard que j'ai vues.

C'est ce que je suis en train d'essayer:

review.forEach(function(p){
   if(p === '\u2022 \u2022 \u2022'){
      console.log('YippeeeE!!!!!!!!!!!!!!!!')
      review.splice(p, 1);
   }
});

Je sais que cela entre dans la if parce que je vois YippeeeeeE!!!!!!!!!!!!! dans la console.

MON PROBLÈME: Je sais que ma boucle for et si la logique sont valables, mais ma tentative de suppression de l'élément actuel du tableau échoue.

PDATE:

J'ai essayé la réponse de Xotic750 et l'élément n'est toujours pas supprimé:

Voici la fonction dans mon code:

review.forEach(function (item, index, object) {
    if (item === '\u2022 \u2022 \u2022') {
       console.log('YippeeeE!!!!!!!!!!!!!!!!')
       object.splice(index, 1);
    }
    console.log('[' + item + ']');
});

Voici la sortie où le tableau n'est toujours pas supprimé:

[Scott McNeil]
[reviewed 4 months ago]
[ Mitsubishi is AMAZING!!!]
YippeeeE!!!!!!!!!!!!!!!!
[• • •]

Il est donc évident que cela va dans la déclaration if comme indiqué, mais il est également évident que le [• • •] est toujours là.

71
novicePrgrmr

On dirait que vous essayez de faire ça?

Itérer et muter un tableau en utilisant Array.prototype.splice

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'b', 'c', 'b', 'a'];

review.forEach(function(item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
});

log(review);
<pre id="out"></pre>

Ce qui fonctionne bien pour un cas simple où vous n'avez pas deux des mêmes valeurs que les éléments de tableau adjacents, sinon vous avez ce problème.

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.forEach(function(item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
});

log(review);
<pre id="out"></pre>

Alors, que pouvons-nous faire pour résoudre ce problème lors de l'itération et de la mutation d'un tableau? Eh bien, la solution habituelle est de travailler en sens inverse. Utiliser ES3 while mais vous pouvez utiliser pour sucre si vous le souhaitez

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a' ,'a', 'b', 'c', 'b', 'a', 'a'],
  index = review.length - 1;

while (index >= 0) {
  if (review[index] === 'a') {
    review.splice(index, 1);
  }

  index -= 1;
}

log(review);
<pre id="out"></pre>

Ok, mais vous vouliez utiliser les méthodes d’itération ES5. Et bien l’option serait d’utiliser Array.prototype.filter mais cela ne modifie pas le tableau d’origine mais en crée un nouveau. Ainsi, même si vous pouvez obtenir la bonne réponse, ce n’est pas ce que vous semblez avoir spécifié .

Nous pourrions également utiliser ES5 Array.prototype.reduceRight , pas pour sa propriété réductrice par sa propriété itération, c’est-à-dire une itération inverse.

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.reduceRight(function(acc, item, index, object) {
  if (item === 'a') {
    object.splice(index, 1);
  }
}, []);

log(review);
<pre id="out"></pre>

Ou nous pourrions utiliser ES5 Array.protoype.indexOf comme si.

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'],
  index = review.indexOf('a');

while (index !== -1) {
  review.splice(index, 1);
  index = review.indexOf('a');
}

log(review);
<pre id="out"></pre>

Mais vous voulez spécifiquement utiliser ES5 Array.prototype.forEach , alors que pouvons-nous faire? Nous devons utiliser Array.prototype.slice pour créer une copie superficielle du tableau et Array.prototype.reverse afin que nous puissions travailler en sens inverse pour muter le tableau d'origine.

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

review.slice().reverse().forEach(function(item, index, object) {
  if (item === 'a') {
    review.splice(object.length - 1 - index, 1);
  }
});

log(review);
<pre id="out"></pre>

Enfin, ES6 nous offre d’autres alternatives, dans lesquelles nous n’avons pas besoin de faire des copies superficielles ni de les inverser. Nous pouvons notamment utiliser Generators and Iterators . Cependant, le soutien est assez faible pour le moment.

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

function* reverseKeys(arr) {
  var key = arr.length - 1;

  while (key >= 0) {
    yield key;
    key -= 1;
  }
}

var review = ['a', 'a', 'b', 'c', 'b', 'a', 'a'];

for (var index of reverseKeys(review)) {
  if (review[index] === 'a') {
    review.splice(index, 1);
  }
}

log(review);
<pre id="out"></pre>

Il convient de noter que, dans tout ce qui précède, si vous retirez NaN du tableau, puis la comparaison avec égaux ne fonctionnera pas, car en Javascript NaN === NaN est faux. Mais nous allons ignorer cela dans les solutions car cela représente encore un cas Edge non spécifié.

Nous avons donc une réponse plus complète avec des solutions qui ont toujours des cas Edge. Le tout premier exemple de code est toujours correct, mais comme indiqué, il ne va pas sans problèmes.

191
Xotic750

Utilisez Array.prototype.filter au lieu de forEach:

var pre = document.getElementById('out');

function log(result) {
  pre.appendChild(document.createTextNode(result + '\n'));
}

var review = ['a', 'b', 'c', 'b', 'a', 'e'];
review = review.filter(item => item !== 'a');
log(review);
28
alemjerus

Vous pouvez aussi utiliser indexOf à la place

var i = review.indexOf('\u2022 \u2022 \u2022');
if (i !== -1) review.splice(i,1);
1
jj689

J'ai compris que vous souhaitiez supprimer du tableau à l'aide d'une condition et disposer d'un autre tableau comportant des éléments supprimés du tableau. Est vrai?

Que dis-tu de ça?

var review = ['a', 'b', 'c', 'ab', 'bc'];
var filtered = [];
for(var i=0; i < review.length;) {
  if(review[i].charAt(0) == 'a') {
    filtered.Push(review.splice(i,1)[0]);
  }else{
    i++;
  }
}

console.log("review", review);
console.log("filtered", filtered);

J'espère que cette aide ...

A propos, j'ai comparé 'for-loop' à 'forEach'.

Si remove dans le cas où une chaîne contient 'f', le résultat est différent.

var review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "Push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"];
var filtered = [];
for(var i=0; i < review.length;) {
  if( review[i].includes('f')) {
    filtered.Push(review.splice(i,1)[0]);
  }else {
    i++;
  }
}
console.log("review", review);
console.log("filtered", filtered);
/**
 * review [  "concat",  "copyWithin",  "entries",  "every",  "includes",  "join",  "keys",  "map",  "pop",  "Push",  "reduce",  "reduceRight",  "reverse",  "slice",  "some",  "sort",  "splice",  "toLocaleString",  "toSource",  "toString",  "values"] 
 */

console.log("========================================================");
review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "Push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"];
filtered = [];

review.forEach(function(item,i, object) {
  if( item.includes('f')) {
    filtered.Push(object.splice(i,1)[0]);
  }
});

console.log("-----------------------------------------");
console.log("review", review);
console.log("filtered", filtered);

/**
 * review [  "concat",  "copyWithin",  "entries",  "every",  "filter",  "findIndex",  "flatten",  "includes",  "join",  "keys",  "map",  "pop",  "Push",  "reduce",  "reduceRight",  "reverse",  "slice",  "some",  "sort",  "splice",  "toLocaleString",  "toSource",  "toString",  "values"]
 */

Et à chaque itération, le résultat est différent.

var review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "Push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"];
var filtered = [];
for(var i=0; i < review.length;) {
  filtered.Push(review.splice(i,1)[0]);
}
console.log("review", review);
console.log("filtered", filtered);
console.log("========================================================");
review = ["of", "concat", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "flatMap", "flatten", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "pop", "Push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toSource", "toString", "unshift", "values"];
filtered = [];

review.forEach(function(item,i, object) {
  filtered.Push(object.splice(i,1)[0]);
});

console.log("-----------------------------------------");
console.log("review", review);
console.log("filtered", filtered);
1
Park Jun-Hong

Voici comment vous devriez le faire:

review.forEach(function(p,index,object){
   if(review[index] === '\u2022 \u2022 \u2022'){
      console.log('YippeeeE!!!!!!!!!!!!!!!!')
      review.splice(index, 1);
   }
});
0
Alaeddin Hussein

Ce qui suit vous donnera tous les éléments qui ne correspondent pas à vos caractères spéciaux!

review = jQuery.grep( review, function ( value ) {
    return ( value !== '\u2022 \u2022 \u2022' );
} );
0
Jenna Leaf