wie man die _.each-Funktion in underscore.js bricht


200

Ich suche nach einer Möglichkeit, Iterationen der _.each()Methode underscore.js zu stoppen , kann aber keine Lösung finden. jQuery .each()kann brechen, wenn Sie dies tun return false.

Gibt es eine Möglichkeit, die Unterstreichung jedes einzelnen () zu stoppen?

_([1,2,3]).each(function(v){
    if (v==2) return /*what?*/;
})

4
Ich denke nicht, dass dies möglich ist, da die native forEachFunktion diese Funktion ebenfalls nicht bietet.
Felix Kling

8
Normalerweise eachmöchten Sie bei Verwendung mit einem Abschluss (in den meisten Sprachen) zuerst Ihre Liste filtern. Auf diese Weise müssen Sie sich keine Sorgen machen, dass Sie davon abbrechen. Wenn Sie eine Iteration frühzeitig abbrechen müssen, gibt es im Allgemeinen wahrscheinlich eine andere Möglichkeit, dies zu tun.
Rob Hruska

Hier sind einige verwandte Fragen für Groovy, bei denen das Verhalten (Unfähigkeit, bequem von einem eachAbschluss abzubrechen ) JavaScript ähnelt.
Rob Hruska

@Dmitry_F, wie andere angemerkt haben, können Sie nicht genau das tun, was Sie verlangen. Aber wie ich gezeigt habe, können Array.everySie das gewünschte Verhalten emulieren.
Aeskr

@Rauben. Prost. Erster Kommentar sehr hilfreich. In der Tat gab es eine andere Art, wie ich es hätte tun können.
net.uk.sweet

Antworten:


267

Sie können nicht von der eachMethode abbrechen - sie emuliert das forEachVerhalten der nativen Methode und die native Methode forEachbietet keine Möglichkeit, der Schleife zu entkommen (außer eine Ausnahme auszulösen).

Es ist jedoch nicht alle Hoffnung verloren! Sie können die Array.everyMethode verwenden. :) :)

Von diesem Link:

everyführt die bereitgestellte callbackFunktion einmal für jedes im Array vorhandene Element aus, bis eines gefunden wird, bei dem callbackein falscher Wert zurückgegeben wird. Wenn ein solches Element gefunden wird, gibt die everyMethode sofort false zurück.

Mit anderen Worten, Sie könnten so etwas tun ( Link zu JSFiddle ):

[1, 2, 3, 4].every(function(n) {
    alert(n);
    return n !== 3;
});

Dies wird 1durch alarmieren 3und dann aus der Schleife "ausbrechen".

Sie verwenden Underscore.js, so dass Sie zufrieden sein werden zu erfahren , dass es nicht ein bietet everyverfahrens sie es nennen every, aber wie der Link erwähnt, sie bieten auch einen Aliasnamen genannt all.


2
Bietet underscore.js auch hierfür eine Implementierung?
Felix Kling

1
@ FelixKling, ja, das tut es. Ich habe das zu meiner Antwort hinzugefügt.
Aeskr

2
Derzeit (05/2013) gibt es weder eine _.every()noch eine _.all()Methode für Arrays mit Unterstrich. Halten Sie sich also an die Array.every().
Pkyeck

3
Dies wird funktionieren, ist aber ein üblicher Grund für die Verwendung every. Achten Sie also auf die Lesbarkeit.
Evanrmurphy

3
Die Unterstreichungsdokumente für enthalten _.each()einen Hinweis speziell auf die Tatsache, dass Sie nicht aus der Schleife ausbrechen können, und empfehlen die Verwendung _.find()stattdessen. http://underscorejs.org/#each
blatt

70

Aktualisieren:

_.find wäre besser, da es aus der Schleife ausbricht, wenn das Element gefunden wird:

var searchArr = [{id:1,text:"foo"},{id:2,text:"bar"}];
var count = 0;
var filteredEl = _.find(searchArr,function(arrEl){ 
              count = count +1;
              if(arrEl.id === 1 ){
                  return arrEl;
              }
            });

console.log(filteredEl);
//since we are searching the first element in the array, the count will be one
console.log(count);
//output: filteredEl : {id:1,text:"foo"} , count: 1

** Alt **

Wenn Sie bedingt aus einer Schleife ausbrechen möchten, verwenden Sie _.filter api anstelle von _.each. Hier ist ein Code-Snippet

var searchArr = [{id:1,text:"foo"},{id:2,text:"bar"}];
var filteredEl = _.filter(searchArr,function(arrEl){ 
                  if(arrEl.id === 1 ){
                      return arrEl;
                  }
                });
console.log(filteredEl);
//output: {id:1,text:"foo"}

1
Dies unterbricht die Schleife nicht - es filtert nur das Array. Stellen Sie sich vor, Sie haben nicht 2, sondern 20.000 Elemente im Array. Ihr Protokoll würde nur das Beispiel ausgeben, das Sie gepostet haben, aber die Schleife würde 20.000 Mal ausgeführt :(
pkyeck

@pkyeck Sie haben Recht, vielleicht ist _.find besser als _.filter, da es bricht, nachdem das Element gefunden wurde, hier ist die Geige: jsfiddle.net/niki4810/9K3EV
Nikhil

2
Ich denke, diese Antwort sollte als die richtige markiert werden. _.findmacht genau das, was gefragt wird: iteriere durch die Liste, bis der Rückruf zurückkehrt true.
Fabien Quatravaux

Für diese Antwort gestimmt, da die akzeptierte Antwort (Array.every) nicht für Objekte funktioniert, _.find () jedoch.
Matt

Und das wird in den Dokumenten empfohlen: Es ist auch gut zu beachten, dass nicht jede Schleife herausgebrochen werden kann - um zu brechen, verwenden Sie stattdessen _.find.
Shaharsol

15

Sie können _.somestattdessen einen Blick darauf werfen _.each. _.somestoppt das Durchlaufen der Liste, sobald ein Prädikat wahr ist. Ergebnis (e) können in einer externen Variablen gespeichert werden.

_.some([1, 2, 3], function(v) {
    if (v == 2) return true;
})

Siehe http://underscorejs.org/#some



3

Vielleicht möchten Sie unterstriches any () oder find (), das die Verarbeitung beendet, wenn eine Bedingung erfüllt ist.



3

Sie können einen forEachUnterstrich nicht unterbrechen, da er das native Verhalten von EcmaScript 5 emuliert.


2

Ich glaube, wenn Ihr Array tatsächlich ein Objekt wäre, könnten Sie es mit einem leeren Objekt zurückgeben.

_.({1,2,3,4,5}).each(function(v){  
  if(v===3) return {}; 
});

Dies geschieht nur mit EcmaScript v <5, da der Vergleich, den der Unterstrich durchführt, um zu überprüfen, ob Sie das leere Objekt in der bereitgestellten Alternative zu forEach zurückgeben, nur durchgeführt wird, wenn das native Objekt nicht verfügbar ist.
Alfonso de la Osa


1

Aktualisieren:

Sie können tatsächlich "brechen", indem Sie einen Fehler nach innen werfen und nach außen abfangen: so etwas:

try{
  _([1,2,3]).each(function(v){
    if (v==2) throw new Error('break');
  });
}catch(e){
  if(e.message === 'break'){
    //break successful
  }
}

Dies hat offensichtlich einige Auswirkungen auf andere Ausnahmen, die Ihr Code in der Schleife auslöst. Gehen Sie also vorsichtig vor!


Ich liebe es, wie ich so viele Abstimmungen dafür bekomme, und dieser Typ bekommt eine ganze Menge
bm_i

1
Ich bin zu spät zur Party, aber beachte, dass der Typ nicht nur gesagt hat, was du vorgeschlagen hast, sondern auch zwei weitere Alternativen angeboten hat (und besser geeignet ist). Das bot der "Hack" nur für den Fall an, dass der Benutzer es auf jeden Fall will. Sie haben stattdessen nur den hässlichen Hack angeboten.
Areks

0

hat in meinem Fall funktioniert

var arr2 = _.filter(arr, function(item){
    if ( item == 3 ) return item;
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.