[解決済み] forEachループで配列から要素を削除するには?
質問
で配列の要素を削除しようとしています。
forEach
ループで配列の要素を削除しようとしていますが、私が見てきた標準的な解決策で困っています。
これは私が現在試しているものです。
review.forEach(function(p){
if(p === '\u2022 \u2022 \u2022'){
console.log('YippeeeE!!!!!!!!!!!!!!!!')
review.splice(p, 1);
}
});
に入り込んでいるのは分かるのですが
if
に入り込んでいることがわかります。
YippeeeeeE!!!!!!!!!!!!!
が表示されるからです。
MY PROBLEM: 私のforループとifロジックが健全であることは分かっていますが、配列から現在の要素を削除する試みは失敗しています。
UPDATEしてください。
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文に入っていますが、[- -]が残っていることも明らかです。
どうすれば解決するのか?
このようなことをしようとしているようですが?
配列の反復処理と変異を 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を使って の間に を使うこともできますが、その場合は の場合 を使うこともできます。
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は浅いコピーを作成し、それを反転させる必要がない、いくつかのさらなる選択肢を提供しています。注目すべきは ジェネレータとイテレータ . しかし、現在のところサポートはかなり低いです。
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>
上記の中で注意すべきことは、もしあなたが
NaN
を配列から取り除いた場合、等号での比較はうまくいきません。なぜなら、Javascriptでは
NaN === NaN
は偽だからです。しかし、それはまた別の未特定のエッジケースであるため、解決策ではそれを無視するつもりです。
これで、まだエッジケースがある解決策を含む、より完全な答えが得られました。一番最初のコード例はまだ正しいのですが、前述のように問題がないわけではありません。
関連
-
Vueの「データを聴く」原則を解説
-
[解決済み] テスト
-
JavaScriptのStringに関する共通メソッド
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] jQueryで要素が非表示になっているかどうかを確認するには?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] forEachループでasync/awaitを使用する
-
[解決済み】PHPの'foreach'は実際どのように動作するのですか?
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JavaScriptにおけるマクロタスクとミクロタスクの詳細
-
vue ディレクティブ v-html と v-text
-
vueが定義するプライベートフィルタと基本的な使い方
-
[解決済み】SyntaxError: JSONの位置1に予期しないトークンoがある。
-
[解決済み】React - TypeError: 未定義のプロパティ 'props' を読み取ることができない。
-
フロントエンド非同期(アシンク)ソリューション(全ソリューション)
-
フロントエンド null のプロパティ 'disabled' を読み取れない 問題が解決された
-
Uncaught TypeError: null のプロパティ 'offsetHeight' を読み取れませんでした。
-
JSクリックイベント - Uncaught TypeError: プロパティ 'onclick' に null を設定できません。
-
JavaScriptのgetElementById()メソッド入門