Quel est le meilleur moyen de rompre avec les boucles imbriquées 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.
}
}
}
}
Tout comme 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
}
}
}
comme défini dans la section 12.12 du document EMCA-262. [Documents MDN]
Contrairement à C, ces étiquettes ne peuvent être utilisées que pour continue
et break
, car Javascript n'a pas goto
.
Enveloppez cela dans une fonction puis return
.
Je suis un peu en retard à la fête, mais voici une approche indépendante de la langue qui n'utilise ni GOTO/labels ni fonctions encapsulées:
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
}
}
}
En revanche, cela coule naturellement, ce qui devrait plaire à la foule des non-GOTO. En revanche, la boucle interne doit terminer l'itération en cours avant la fin, de sorte qu'elle pourrait ne pas être applicable dans certains scénarios.
Je réalise que c’est un sujet très ancien, mais comme mon approche standard n’est pas encore définie, j’ai pensé le poster pour les futurs 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
}
Comment ça :)
assez facile
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;}
}
Pourquoi ne pas utiliser aucune pause du tout, aucun indicateur d'abandon et aucune vérification de condition supplémentaire. Cette version analyse uniquement les variables de la boucle (les rend Number.MAX_VALUE
) lorsque la condition est remplie et force toutes les boucles à se terminer élégamment.
// 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
}
}
}
Il y avait une réponse similaire pour les boucles imbriquées de type décrémentant, mais cela fonctionne pour les boucles imbriquées de type incrémenté sans qu'il soit nécessaire de prendre en compte la valeur de terminaison de chaque boucle pour les boucles simples.
Un autre exemple:
// 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
}
}
}
}
}
Que diriez-vous de pousser les boucles à leurs limites
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 vous utilisez Coffeescript, il existe un mot-clé "do" qui facilite la définition et l'exécution immédiate d'une fonction anonyme:
do ->
for a in first_loop
for b in second_loop
if condition(...)
return
... afin que vous puissiez simplement utiliser "return" pour sortir des boucles.
Je pensais montrer une approche de programmation fonctionnelle. Vous pouvez sortir des fonctions imbriquées Array.prototype.some () et/ou Array.prototype.every (), comme dans mes solutions. Un avantage supplémentaire de cette approche est que Object.keys()
énumère uniquement les propriétés énumérables propres à un objet, tandis que "une boucle for-in énumère également les propriétés de la chaîne de prototypes" .
Proche de la solution de l'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;
}
Solution qui réduit les itérations sur les titres/éléments:
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;
}
});
});
Hmmm salut à la fête de 10 ans?
Pourquoi ne pas mettre une condition dans votre pour?
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
}
}
}
Comme ça tu t'arrêtes quand tu veux
Dans mon cas, en utilisant TypeScript, nous pouvons utiliser une méthode () qui parcourt le tableau et s’arrête lorsque la condition est remplie. Ainsi, mon code devient comme ceci:
Args.some((listObj) => {
return listObj.some((obj) => {
return !(obj == "[condition]")
})
})
Comme cela, la boucle s'est arrêtée juste après que la condition soit remplie
Rappel: Ce code est exécuté en TypeScript
Voici cinq manières de sortir des boucles imbriquées en JavaScript:
1) Place la boucle parent (s) à la fin
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
{
i = 5;
break;
}
}
}
2) Utiliser l'étiquette
exit_loops:
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
break exit_loops;
}
}
3) Utiliser 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) Utiliser la fonction d'exécution automatique
(function()
{
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
return;
}
}
})();
5) Utiliser la fonction régulière
function nested_loops()
{
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (j === 2)
return;
}
}
}
nested_loops();
Déjà mentionné précédemment par swilliams , mais avec un exemple ci-dessous (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);
}