web-dev-qa-db-ja.com

forEachループで配列から要素を削除する方法は?

forEachループで配列内の要素を削除しようとしていますが、私が見た標準的な解決策に問題があります。

これは私が現在試していることです:

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

コンソールにYippeeeeeE!!!!!!!!!!!!!が表示されているため、ifになっていることがわかります。

私の問題: forループとifロジックが健全であることは知っていますが、配列から現​​在の要素を削除する試みは失敗します。

更新:

Xotic750の答えを試してみましたが、要素はまだ削除されていません。

コード内の関数は次のとおりです。

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

配列がまだ削除されていない出力は次のとおりです。

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

したがって、明らかに、指示どおりにifステートメントに進んでいますが、[•••]がまだ存在することも明らかです。

66
novicePrgrmr

これをやろうとしているように見えますか?

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>

これは、隣接する配列項目と同じ値が2つない単純な場合にうまく機能します。そうでない場合、この問題が発生します。

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>

それでは、配列を繰り返し、変更するときにこの問題について何ができるでしょうか?さて、通常の解決策は逆に作業することです。 ES3 while を使用しますが、必要に応じて for sugarを使用できます

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>

わかりましたが、ES5反復法を使用したいと考えていました。まあ、オプションは Array.prototype.filter を使用することですが、これは元の配列を変更せずに新しい配列を作成するため、正しい答えを得ることができますが、指定したようには見えません。

また、ES5 Array.prototype.reduceRight を使用することもできます。反復プロパティによる縮小プロパティではなく、逆方向の反復です。

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>

または、ES5 Array.protoype.indexOf を使用することもできます。

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>

しかし、あなたは特にES5 Array.prototype.forEach を使用したいので、何ができるでしょうか? Array.prototype.slice を使用して配列の浅いコピーを作成し、 Array.prototype.reverse を使用して、元の配列を変更するために逆に作業する必要があります。

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>

最後に、ES6には、浅いコピーを作成してそれらを逆にする必要のない、さらに別の選択肢があります。特に Generators and Iterators を使用できます。ただし、現時点ではサポートはかなり低くなっています。

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>

上記のすべてで注意すべきことは、JavascriptではNaN === NaNがfalseであるため、配列から NaN を除去する場合、equalsとの比較は機能しないということです。しかし、解決策ではそれを無視しますが、それはもう1つの不特定のEdgeケースです。

エッジケースがまだ残っているソリューションを使用した、より完全な答えです。最初のコード例はまだ正しいですが、述べられているように、問題がないわけではありません。

188
Xotic750

forEachの代わりにArray.prototype.filterを使用します。

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);
24
alemjerus

代わりにindexOfを使用してこれを行うこともできます

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

条件を使用して配列から削除し、配列からアイテムを削除した別の配列を作成する必要があることを理解しました。は正しい?

これはどう?

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

このヘルプを願っています...

ところで、「for-loop」と「forEach」を比較しました。

文字列に「f」が含まれる場合に削除すると、結果は異なります。

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

各反復で削除し、結果も異なります。

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

これを行う方法は次のとおりです。

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

以下は、あなたの特殊文字と等しくないすべての要素を提供します!

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