637 votes

Quelle est la meilleure façon de se libérer des boucles imbriquées en JavaScript ?

Quelle est la meilleure façon de se libérer des 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.
         }
      }
   }
}

0 votes

Voici un bon exemple pour sortir des boucles et des blocs de code : marcin-chwedczuk.github.io/

1453voto

ephemient Points 87003

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

tel que défini à l'article 12.12 de l'EMCA-262. [MDN Docs]

Contrairement à C, ces étiquettes ne peuvent être utilisées que pour continue y break car Javascript n'a pas goto .

0 votes

Intéressant ! Je n'avais pas réalisé qu'on pouvait se casser à un label.

5 votes

Est-ce que c'est "casser à une étiquette" ? On dirait plutôt que vous nommez un bloc avec n boucles éventuellement imbriquées et que vous interrompez la "marche dans le bloc" en appelant break {label}.

9 votes

@NielsBom Vous avez raison : il sort de la boucle avec l'étiquette donnée. Il ne sort pas goto le label. Vous êtes essentiellement en train de nommer une boucle et de dire que je veux sortir de telle ou telle boucle.

236voto

swilliams Points 19415

Enveloppez tout ça dans une fonction et ensuite return .

0 votes

Je ne suis pas l'auteur de la question, mais je pense que c'est facile ? celle d'ephemient est tout aussi valable, bien que syntaxiquement je n'aime pas ce genre d'étiquettes. Cela ressemble un peu à GOTO - mais je ne veux pas ouvrir cette boîte de Pandore ici.

15 votes

Je choisis d'accepter cette réponse car elle est simple et peut être mise en œuvre de manière élégante. Je déteste absolument les GOTO et les considère comme une mauvaise pratique ( peut ouvrir ), celui d'Ephemient est trop proche ;o)

18 votes

IMO, les GOTO sont bien tant qu'ils ne brisent pas la structure. Mais chacun son truc !

103voto

aleemb Points 12138

J'arrive un peu tard dans la soirée, mais ce qui suit est une approche indépendante du langage qui n'utilise pas les GOTO/étiquettes ou les enveloppes de fonctions :

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

D'un point de vue positif, le processus se déroule naturellement, ce qui devrait plaire aux personnes qui n'utilisent pas GOTO. En revanche, la boucle interne doit terminer l'itération en cours avant de se terminer, ce qui peut ne pas être applicable dans certains scénarios.

3 votes

L'accolade d'ouverture ne doit pas être sur une nouvelle ligne, car les implémentations js peuvent insérer un deux-points à la fin de la ligne précédente.

27 votes

@Evgeny : alors que certains guides de style JavaScript demandent que les accolades ouvrantes soient sur la même ligne, il n'est pas incorrect de les avoir sur une nouvelle ligne et il n'y a pas de danger que l'interpréteur insère un point-virgule de manière ambiguë. Le comportement de l'ASI est bien défini et ne s'applique pas ici.

11 votes

Assurez-vous simplement de commenter cette approche. Ce n'est pas immédiatement évident de comprendre ce qui se passe ici.

87voto

zord Points 1315

Je me rends compte que c'est un sujet très ancien, mais comme mon approche standard n'est pas encore là, j'ai pensé le poster pour les futurs googleurs.

var a, b, abort = false;
for (a = 0; a < 10 && !abort; a++) {
    for (b = 0; b < 10 && !abort; b++) {
        if (condition) {
            doSomeThing();
            abort = true;
        }
    }
}

2 votes

Si le condition évalue à true à la première itération de la boucle imbriquée, vous continuez à parcourir le reste des 10 itérations, en vérifiant la valeur abort à chaque fois. Ce n'est pas un problème de performance pour 10 itérations, mais ce le serait avec, disons, 10 000.

9 votes

Non, il sort des deux boucles. Voici la démonstration violon . Quelle que soit la condition que vous définissez, elle se termine une fois qu'elle est remplie.

7 votes

L'optimisation consisterait à ajouter un break ; après avoir défini abort = true ; et à supprimer la vérification de la condition !abort de la boucle finale.

44voto

harley.333 Points 1509
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 c'est ? :)

2 votes

Je me suis dit que c'était là où Swilliams voulait en venir.

0 votes

Merci de l'expliquer explicitement comme ça. J'oublie toujours que je peux envelopper n'importe quel morceau de code arbitraire dans une fonction anonyme et l'appeler.

21 votes

Cela ajoute un coût d'exécution significatif si la boucle est grande - un nouveau contexte d'exécution pour la fonction doit être créé (et à un moment donné libéré par GC) par l'interprète/compilateur Javascript (ou, "compilateur" de nos jours, un mélange des deux) À CHAQUE FOIS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X