Pregunta

¿Cuál es la mejor manera de romper los bucles anidados en 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.
         }
      }
   }
}
¿Fue útil?

Solución

Al igual que 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
            }
        }
    }

como se define en EMCA-262 sección 12.12. [MDN Docs]

A diferencia de C, estas etiquetas solo se pueden usar para continue y break , ya que Javascript no tiene goto .

Otros consejos

Envuelva eso en una función y luego simplemente return .

Llego un poco tarde a la fiesta, pero el siguiente es un enfoque independiente del idioma que no utiliza GOTO / etiquetas ni ajuste de funciones:

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
      }
   }
}

Por el lado positivo, fluye naturalmente, lo que debería complacer a la multitud que no es GOTO. En el lado negativo, el ciclo interno necesita completar la iteración actual antes de terminar, por lo que podría no ser aplicable en algunos escenarios.

Me doy cuenta de que este es un tema muy antiguo, pero dado que mi enfoque estándar aún no está aquí, pensé en publicarlo para los futuros googlers.

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
}

¿Cómo es eso? :)

bastante simple

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;}
}

¿Qué tal si no se usan interrupciones, no hay marcas de cancelación y no se realizan comprobaciones adicionales de condición? Esta versión solo dispara las variables de bucle (las convierte en Number.MAX_VALUE ) cuando se cumple la condición y obliga a todos los bucles a terminar con elegancia.

// 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
    }
  }
}

Hubo una respuesta similar para los bucles anidados de tipo decreciente, pero esto funciona para los bucles anidados de tipo incremental sin necesidad de considerar el valor de terminación de cada bucle para bucles simples.

Otro ejemplo:

// 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
        }
      }
    }
  }
}

Aquí hay cinco formas de salir de los bucles anidados en JavaScript:

1) Establecer el ciclo de los padres hasta el final

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

2) Usar etiqueta

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

3) Usar variable

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) Usar la función de ejecución automática

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

5) Usar la función regular

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

¿Qué tal si llevamos los bucles a sus límites finales?

    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;
            }
         }
       }
     }

Si usa Coffeescript, hay un conveniente '' do '' palabra clave que facilita la definición y ejecución inmediata de una función anónima:

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

... para que pueda simplemente usar " return " para salir de los bucles.

Pensé en mostrar un enfoque de programación funcional. Puede salir de las funciones anidadas Array.prototype.some () y / o Array.prototype.every (), como en mis soluciones. Un beneficio adicional de este enfoque es que Object.keys () enumera solo las propiedades enumerables de un objeto, mientras que " un ciclo for-in enumera también las propiedades en la cadena del prototipo " .

Cerca de la solución del OP:

    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;
    }

Solución que reduce la iteración sobre los Encabezados / Elementos:

    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;
            }
        });
    });

Ya mencionado anteriormente por swilliams , pero con un ejemplo a continuación (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, hola a la fiesta de los 10 años?

¿Por qué no poner alguna condición en tu para?

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
        }
    }
}

De esta manera te detienes cuando quieres

En mi caso, usando el Script mecanografiado, podemos usar algunos () que atraviesan la matriz y se detienen cuando se cumple la condición Entonces mi código se vuelve así:

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

De esta manera, el ciclo se detuvo justo después de que se cumpla la condición

Recordatorio: este código se ejecuta en 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;
};

la mejor manera es -
1) Ordene los dos conjuntos que se utilizan en el primer y segundo bucle.
2) si el elemento coincide, rompa el bucle interno y mantenga el valor del índice.
3) cuando comience la próxima iteración, inicie el bucle interno con el valor de índice de retención.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top