2016-06-16 13 views
7
var myArray = [1,2,3,4,5,6,7,8,9]; 

function isOdd(value){ 
    return value % 2; 
} 

for(var i = 0; i < myArray.length; i++){ 
    if(isOdd(myArray[i])){ 
     myArray.splice(i,1); 
     i--; 
    } 
} 

上記のコードは任意の長さの配列をとり、各値をチェックします。配列のビットの値が任意の条件を満たす場合(この場合は奇数の場合)、アレイから削除されます。JS配列の値をループして値を削除するときに、代わりにwhileを使用する必要がありますか?

Array.prototype.splice()は、配列から値を削除するために使用されます。そして、iは、削除された値が残っているギャップを埋めるために配列 "移動する"の残りの値を考慮して減算されます値をスキップする)。

しかし、iが配列の長さと等しい場合、forループは終了します。これは値が削除されるにつれて短くなります。

myArray.lengthの値は、ループの進行に伴って動的に減少するか、ループの開始時に値を保存し、値が削除されると更新されませんか?後者の場合は、ループを修正するために何ができますか?

ありがとうございました!

答えて

3

myArray.lengthは、アレイの操作によって変更されています。しかし、ループやスプライシングは、適切なパッドが付いていないと、望ましくない結果につながります。

不要な訂正を防ぐには、最後からwhileループを使用して残りの配列を処理します。

function isOdd(value) { 
 
    return value % 2; 
 
} 
 

 
var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9], 
 
    i = myArray.length; 
 

 
while (i--) { 
 
    if (isOdd(myArray[i])) { 
 
     myArray.splice(i, 1); 
 
    } 
 
} 
 
console.log(myArray);

+0

私がすることをお勧めしたいです高次の 'Array.prototype.filter()'メソッドがこの種の操作のためのより良い選択です。 'filter()'メソッドに依存するコードはかなり簡潔であり、私はかなり読みやすいと言います。 – Tex

+0

あなたは正しいですが、問題はスプライスとループの欠点です。 –

+0

@Tex - '.filter()'は確実に使いやすいですが、OPと同じ実装ではない元の配列を変更するのではなく、新しい配列を作成します。場合によっては、他のコードにこの配列への参照がある場合は、新しい配列で置き換えるのではなく、配列を変更することがあります。 – jfriend00

0

lengthプロパティはすべての反復で読み込まれ、スプライスメソッドはその値を更新するので、期待通りに機能します。しかし、これは良いコーディング方法ではないと言いますが、whileループははるかに読みやすく、明白な選択でなければなりません。あなた代わりに使用forwhileする必要はありませんが、あなたは間違いなくをすべき:

は直接質問に答えるために。

0

使用Array.filter代わり

var myArray = [1,2,3,4,5,6,7,8,9]; 
 
myArray=myArray.filter(function(item,index) { 
 
return !(item % 2); 
 
}) 
 

 
console.log(myArray)

0

あなたは絶対に元を変更する必要はありません場合は、Array.prototype.filter()を使用したいと思います場所ですアレイ、インプレース

splice()の都度、配列の.lengthプロパティが更新されていると思われます。 filter()メソッドは、この種の操作のために作成されました。

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isOdd(value){ 
 
    return value % 2; 
 
} 
 

 
var filteredArray = myArray.filter(function(item){ 
 
    return !isOdd(item); 
 
}); 
 
    
 
console.log(filteredArray);

上記のコードのより簡潔なバージョン:

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isEven(value){ 
 
    return value % 2 === 0; 
 
} 
 
    
 
var filteredArray = myArray.filter(isEven); 
 

 
console.log(filteredArray);

ES6矢印構文に依存一層簡潔バージョン:

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
var isEven = value => value % 2 === 0; 
 
    
 
var filteredArray = myArray.filter(isEven); 
 

 
console.log(filteredArray);

そして、あなたは絶対にインプレース配列を編集する必要があります/ここsplice()を使用する場合には、私がArray.prototype.forEach()for以上またはwhileループを使用することをお勧めします。 forEach()は、定型化されていない機能で同じ機能を実現できる高次の方法です。ほとんどの高次メソッド/関数と同様に、それはあなたが行う必要があるものを正確に行うよりもむしろ定義することに集中することを可能にします。

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isOdd(value){ 
 
    return value % 2; 
 
} 
 

 
myArray.forEach(function(c, i, a){ 
 
    if(isOdd(c)){ 
 
     a.splice(i,1); 
 
    } 
 
}) 
 

 
console.log(myArray);

0

あなたはそれらの両方を使用することができますし、それはあなたが好きどちらに依存します。あなたがwhile loopを使用することを好むならば、ニーナさんanswerはよさそうだし、あなたがfor loopを使用したい場合は、その後、完全に自分でカウンターの変更を管理するために検討したり、長さが変化する場合:

function isOdd(value) { 
 
    return value % 2; 
 
} 
 

 
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 
 

 
for (var i = 0; i < arr1.length;) 
 
    isOdd(arr1[i]) ? arr1.splice(i, 1) : i++; 
 
console.log(arr1); 
 

 
var arr2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 
 

 
for (var i = 0; i < arr2.length; i++) 
 
    if (isOdd(arr2[i])) { 
 
    arr2.splice(i, 1); 
 
    i--; 
 
    } 
 
console.log(arr2);

関連する問題