cursor.forEach()の「続行」


280

meteor.jsとMongoDBを使用してアプリを構築していますが、cursor.forEach()について質問があります。各forEach反復の最初にいくつかの条件を確認し、その要素に対して操作を実行する必要がない場合は要素をスキップして、時間を節約したいと思います。

これが私のコードです:

// Fetch all objects in SomeElements collection
var elementsCollection = SomeElements.find();
elementsCollection.forEach(function(element){
  if (element.shouldBeProcessed == false){
    // Here I would like to continue to the next element if this one 
    // doesn't have to be processed
  }else{
    // This part should be avoided if not neccessary
    doSomeLengthyOperation();
  }
});

cursor.find()。fetch()を使用してカーソルを配列に変換し、通常のforループを使用して要素を反復処理し、継続と中断を通常どおり使用できることを知っていますが、forEach( )。

回答:


562

を繰り返すたびに、指定しforEach()た関数が呼び出されます。特定の反復内でさらに処理を停止するには(そして次の項目に進みます)return、適切な時点で関数を実行する必要があります。

elementsCollection.forEach(function(element){
  if (!element.shouldBeProcessed)
    return; // stop processing this iteration

  // This part will be avoided if not neccessary
  doSomeLengthyOperation();
});

18
継続が単に「リターン」である場合、「ブレーク」とは何かを知っていますか。
Drag0

5
私はMongoDBを使用していないため、そのドキュメントをまだ読んでいませんがreturn false;break;(jQuery .each()ループの場合と同様)と同等の可能性があります。もちろん、MongoDBを実装した人に.forEach()は他のアイデアがあったかもしれません...
nnnnnn 2013

10
@ Drag0 .forEach()の代わりに.some()を使用できます。これにより、falseを返してループを解除できます。
Andrew

6
@Andrewを使用できsomeますが、条件に一致する要素があるかどうかを判断するための関数を誤用している(または創造的に使用している)ことに注意してください。私は、人々が使用見たときの種類などmap、結果を無視する(彼らが使用している必要がありますforEach)。それの意味を、人々はあなたが使用している理由を知るために二度見する必要がありますsomeあなたが本当に結果を気にしないとき
フアン・メンデス

1
@Andrewのすばらしいヒントですが、return trueこれはいくつかのループを壊します
daviestar '28

11

私の意見では、ブロックを返すことは無意味なので、このfilter メソッドを使用してこれを達成するための最良のアプローチforEachです。スニペットの例:

// Fetch all objects in SomeElements collection
var elementsCollection = SomeElements.find();
elementsCollection
.filter(function(element) {
  return element.shouldBeProcessed;
})
.forEach(function(element){
  doSomeLengthyOperation();
});

これにより、絞り込まれ、処理する必要のある要素elementsCollectionのみが保持されますfiltred


3
これは、見つかった要素を2回繰り返します。1回filter目は2回目、2回目は2回目forEachです。大規模なコレクションの場合、非常に非効率的です
認知症

1
あなたは正しいですが、これの時間の複雑さはO(2n)と見なすことができるので、それは大した問題ではないと思いますO(n)
Ramy Tamer 2017

2
SOがOPだけでなく他のユーザーによって使用されていることを考えると、SOを投稿する目的でのみソリューションを投稿すると、良いことよりも害が大きくなります。上記の答えは、1回の繰り返しでrightそれを実行し、それを行う方法です。
2017

OPのコレクションは配列ではなく、Mongo DBカーソルオブジェクトであることに注意してください。これには.filter()メソッドがないようです。そのため、その.toArray()前にそのメソッドを呼び出す必要があります.filter()
nnnnnn

7

以下は、の代わりにを使用for ofしたソリューションcontinueですforEach


let elementsCollection = SomeElements.find();

for (let el of elementsCollection) {

    // continue will exit out of the current 
    // iteration and continue on to the next
    if (!el.shouldBeProcessed){
        continue;
    }

    doSomeLengthyOperation();

});

ループ内で動作しない非同期関数をループ内で使用する必要がある場合、これはもう少し便利かもしれませんforEach。例えば:


(async fuction(){

for (let el of elementsCollection) {

    if (!el.shouldBeProcessed){
        continue;
    }

    let res;

    try {
        res = await doSomeLengthyAsyncOperation();
    } catch (err) {
        return Promise.reject(err)
    }

});

})()

2

JavaScript の短絡評価を利用する。もしel.shouldBeProcessed、trueを返しますdoSomeLengthyOperation

elementsCollection.forEach( el => 
  el.shouldBeProcessed && doSomeLengthyOperation()
);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.