Domanda

Qual è il modo migliore per interrompere i loop nidificati in Javascript?

//Write the links to the page.
for (var x = 0; x < Args.length; x++)
{
   for (var Heading in Navigation.Headings)
   {
      for (var Item in Navigation.Headings[Heading])
      {
         if (Args[x] == Navigation.Headings[Heading][Item].Name)
         {
            document.write("<a href=\"" 
               + Navigation.Headings[Heading][Item].URL + "\">" 
               + Navigation.Headings[Heading][Item].Name + "</a> : ");
            break; // <---HERE, I need to break out of two loops.
         }
      }
   }
}
È stato utile?

Soluzione

Proprio come Perl,

loop1:
    for (var i in set1) {
loop2:
        for (var j in set2) {
loop3:
            for (var k in set3) {
                break loop2;  // breaks out of loop3 and loop2
            }
        }
    }

come definito nella sezione 12.12 di EMCA-262. [MDN Docs]

A differenza di C, queste etichette possono essere utilizzate solo per continue e break , poiché Javascript non ha goto .

Altri suggerimenti

Riempilo in una funzione e poi return .

Sono un po 'in ritardo alla festa, ma il seguente è un approccio indipendente dal linguaggio che non utilizza GOTO / etichette o wrapping di funzioni:

for (var x = Set1.length; x > 0; x--)
{
   for (var y = Set2.length; y > 0; y--)
   {
      for (var z = Set3.length; z > 0; z--)
      {
          z = y = -1; // terminates second loop
          // z = y = x = -1; // terminate first loop
      }
   }
}

Sul lato positivo scorre naturalmente, il che dovrebbe piacere alla folla non GOTO. Sul lato negativo, il ciclo interno deve completare l'iterazione corrente prima di terminare, quindi potrebbe non essere applicabile in alcuni scenari.

Mi rendo conto che questo è un argomento molto vecchio, ma poiché il mio approccio standard non è ancora qui, ho pensato di pubblicarlo per i futuri googler.

var a, b, abort = false;
for (a = 0; a < 10 && !abort; a++) {
    for (b = 0; b < 10 && !abort; b++) {
        if (condition) {
            doSomeThing();
            abort = true;
        }
    }
}
var str = "";
for (var x = 0; x < 3; x++) {
    (function() {  // here's an anonymous function
        for (var y = 0; y < 3; y++) {
            for (var z = 0; z < 3; z++) {
                // you have access to 'x' because of closures
                str += "x=" + x + "  y=" + y + "  z=" + z + "<br />";
                if (x == z && z == 2) {
                    return;
                }
            }
        }
    })();  // here, you execute your anonymous function
}

Come va? :)

abbastanza semplice

var a=[1,2,3];
var b=[4,5,6];
var breakCheck1=false;

for (var i in a){
    for (var j in b){
        breakCheck1=true;
        break;
    }
    if (breakCheck1) {break;}
}

Che ne dite di usare nessuna pausa, nessun flag di interruzione e nessun controllo delle condizioni extra. Questa versione fa semplicemente saltare le variabili del ciclo (le rende Number.MAX_VALUE ) quando la condizione è soddisfatta e forza tutti i loop a terminare in modo elegante.

// No breaks needed
for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    if (condition) {
      console.log("condition met");
      i = j = Number.MAX_VALUE; // Blast the loop variables
    }
  }
}

Esisteva una risposta simile per i cicli annidati di tipo decrementante, ma questo funziona per i cicli annidati di tipo incrementale senza la necessità di considerare il valore di terminazione di ciascun ciclo per i cicli semplici.

Un altro esempio:

// No breaks needed
for (var i = 0; i < 89; i++) {
  for (var j = 0; j < 1002; j++) {
    for (var k = 0; k < 16; k++) {
      for (var l = 0; l < 2382; l++) {
        if (condition) {
          console.log("condition met");
          i = j = k = l = Number.MAX_VALUE; // Blast the loop variables
        }
      }
    }
  }
}

Ecco cinque modi per uscire dai loop nidificati in JavaScript:

1) Imposta il ciclo parent (s) alla fine

for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
        {
            i = 5;
            break;
        }
    }
}

2) Usa etichetta

exit_loops:
for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
            break exit_loops;
    }
}

3) Usa variabile

var exit_loops = false;
for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
        {
            exit_loops = true;
            break;
        }
    }
    if (exit_loops)
        break;
}

4) Utilizza la funzione di auto-esecuzione

(function()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
})();

5) Utilizza la funzione regolare

function nested_loops()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
}
nested_loops();

Che ne dici di spingere i loop fino ai loro limiti

    for(var a=0; a<data_a.length; a++){
       for(var b=0; b<data_b.length; b++){
           for(var c=0; c<data_c.length; c++){
              for(var d=0; d<data_d.length; d++){
                 a =  data_a.length;
                 b =  data_b.length;
                 c =  data_b.length;
                 d =  data_d.length;
            }
         }
       }
     }

Se usi Coffeescript, c'è un comodo "quot" do " parola chiave che semplifica la definizione e l'esecuzione immediata di una funzione anonima:

do ->
  for a in first_loop
    for b in second_loop
      if condition(...)
        return

... così puoi semplicemente usare " return " per uscire dai circuiti.

Ho pensato di mostrare un approccio di programmazione funzionale. È possibile uscire dalle funzioni nidificate di Array.prototype.some () e / o Array.prototype.every (), come nelle mie soluzioni. Un ulteriore vantaggio di questo approccio è che Object.keys () elenca solo le proprietà enumerabili di un oggetto, mentre " un ciclo for-in elenca anche le proprietà nella catena del prototipo " .

Vicino alla soluzione del PO:

    Args.forEach(function (arg) {
        // This guard is not necessary,
        // since writing an empty string to document would not change it.
        if (!getAnchorTag(arg))
            return;

        document.write(getAnchorTag(arg));
    });

    function getAnchorTag (name) {
        var res = '';

        Object.keys(Navigation.Headings).some(function (Heading) {
            return Object.keys(Navigation.Headings[Heading]).some(function (Item) {
                if (name == Navigation.Headings[Heading][Item].Name) {
                    res = ("<a href=\""
                                 + Navigation.Headings[Heading][Item].URL + "\">"
                                 + Navigation.Headings[Heading][Item].Name + "</a> : ");
                    return true;
                }
            });
        });

        return res;
    }

Soluzione che riduce l'iterazione su intestazioni / elementi:

    var remainingArgs = Args.slice(0);

    Object.keys(Navigation.Headings).some(function (Heading) {
        return Object.keys(Navigation.Headings[Heading]).some(function (Item) {
            var i = remainingArgs.indexOf(Navigation.Headings[Heading][Item].Name);

            if (i === -1)
                return;

            document.write("<a href=\""
                                         + Navigation.Headings[Heading][Item].URL + "\">"
                                         + Navigation.Headings[Heading][Item].Name + "</a> : ");
            remainingArgs.splice(i, 1);

            if (remainingArgs.length === 0)
                return true;
            }
        });
    });

Già menzionato in precedenza da swilliams , ma con un esempio in basso (Javascript):

// Function wrapping inner for loop
function CriteriaMatch(record, criteria) {
  for (var k in criteria) {
    if (!(k in record))
      return false;

    if (record[k] != criteria[k])
      return false;
  }

  return true;
}

// Outer for loop implementing continue if inner for loop returns false
var result = [];

for (var i = 0; i < _table.length; i++) {
  var r = _table[i];

  if (!CriteriaMatch(r[i], criteria))
    continue;

  result.add(r);
}

Hmmm ciao alla festa di 10 anni?

Perché non mettere qualche condizione nel tuo per?

var condition = true
for (var i = 0 ; i < Args.length && condition ; i++) {
    for (var j = 0 ; j < Args[i].length && condition ; j++) {
        if (Args[i].obj[j] == "[condition]") {
            condition = false
        }
    }
}

In questo modo ti fermi quando vuoi

Nel mio caso, usando Typescript, possiamo usare alcuni () che attraversano l'array e si fermano quando viene soddisfatta la condizione Quindi il mio codice diventa così:

Args.some((listObj) => {
    return listObj.some((obj) => {
        return !(obj == "[condition]")
    })
})

In questo modo, il ciclo si è interrotto subito dopo aver soddisfatto la condizione

Promemoria: questo codice viene eseguito in TypeScript

XXX.Validation = function() {
    var ok = false;
loop:
    do {
        for (...) {
            while (...) {
                if (...) {
                    break loop; // Exist the outermost do-while loop
                }
                if (...) {
                    continue; // skips current iteration in the while loop
                }
            }
        }
        if (...) {
            break loop;
        }
        if (...) {
            break loop;
        }
        if (...) {
            break loop;
        }
        if (...) {
            break loop;
        }
        ok = true;
        break;
    } while(true);
    CleanupAndCallbackBeforeReturning(ok);
    return ok;
};

il modo migliore è -
1) Ordinare entrambi gli array utilizzati nel primo e nel secondo loop.
2) se l'oggetto corrisponde, interrompi il ciclo interno e mantieni il valore dell'indice.
3) quando inizia la prossima iterazione avvia il ciclo interno con il valore dell'indice di mantenimento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top