Si «break» est appelé à l'intérieur d'une fonction récursive, cela interrompra-t-il toutes ses itérations ou va-t-il simplement annuler cette instance? Plus précisément, je veux connaître le code suivant:

//take a 2d array and check if it is in _switch
function checkSwitch(arr2d, rates, n = 0, found = []){
    if(n===arr2d.length){
        inCase(found, rates)
        break
    }
    for(let i in arr2d[n]){
        if(deepCheck(_switch, [...found, arr2d[n][i]]))
        checkSwitch(arr2d, rates, n+1, [...found, arr2d[n][i]])
    }
    return false
}

J'ai un tableau 2d (tableau de tableaux) et je vérifie si un élément de chacun des tableaux est inclus en tant que clés d'objet imbriquées dans ce _switch que je fais. Lorsque j'ai une correspondance complète, exécutez une fonction et je souhaite continuer à vérifier le tableau 2d pour voir s'il existe d'autres correspondances.

Cependant , si jamais je tombe sur un tableau sans correspondance, je dois interrompre toutes les itérations de la récursivité pour plus d'efficacité, car je sais qu'il ne peut logiquement y avoir de correspondance d'une par chacune.

J'ai donc besoin de pouvoir casser une instance et toutes les casser. Je ne sais pas comment l'obtenir.

CODE CORRIGÉ ET LEÇONS APPRISES Je suis étonné de voir à quel point j'apprends ce qu'est réellement l'intelligence en travaillant sur l'intelligence artificielle. Dans une fonction récursive, l'ajout d'une valeur de retour cassera l'instance actuelle et si vous vérifiez le retour lors de l'appel de la récursivité, vous pouvez renvoyer l'effondrement de la récursivité entière. Voici le nouveau code:

function checkSwitch(arr2d, rates, n = 0, found = []) {
    if (n === arr2d.length) {
        inCase(found, rates);
        return true;
    }
    let tf = false
    for (let i in arr2d[n]) {
        if (deepCheck(_switch, [...found, arr2d[n][i]])) {
            if (!checkSwitch(arr2d, rates, n + 1, [...found, arr2d[n][i]])) {
                return false;
            } else {
                tf = true
            }
        }
    }
    return tf;
}

Renvoyer vrai signifie rompre cette itération et continuer, tandis que retourner faux signifie tout casser. J'ai ajouté une bascule juste avant la boucle for pour que si nous obtenons une correspondance de l'un de chaque tableau, alors nous devons logiquement vérifier toutes les autres possibilités car elles peuvent être valides. sinon, si nous traversons le for sans obtenir un vrai, alors tout casser car il n'y a plus de possibilités.

0
user10302261 20 nov. 2018 à 06:46

3 réponses

Meilleure réponse

Vous pouvez simplement utiliser return à la place et toujours vérifier le résultat du point de vue de l'appelant. Dans ce cas, vous devrez renvoyer une valeur différente lorsqu'elle "se cassera":

function checkSwitch(arr2d, rates, n = 0, found = []) {
  if (n === arr2d.length) {
    inCase(found, rates);
    return true;
  }
  for (let i in arr2d[n]) {
    if (deepCheck(_switch, [...found, arr2d[n][i]])) {
      if (checkSwitch(arr2d, rates, n + 1, [...found, arr2d[n][i]])) {
        return true;
      }
    }
  }
  return false;
}

Ici, retourner true signifie essentiellement "tout arrêter" (éclatement), et retourner false signifie arrêter l'itération en cours normalement (comme OP l'a expliqué lui-même dans les commentaires ci-dessous).

Techniquement, cela ne "se décompose" pas, mais au lieu de cela, vous remonterez la chaîne d'appels avant de revenir, ce qui est (à mon humble avis) l'approche la plus propre (bien que techniquement pas aussi optimale que la rupture en une seule fois) si vous allez vous en tenir à un fonction récursive.

0
Jeto 20 nov. 2018 à 04:38

Ni. Les instructions de contrôle de boucle comme break et continue ne sont valides qu'à l'intérieur d'une boucle (for, while, do ou switch). L'instruction break dans votre code n'est pas dans une boucle, donc ce code provoquera une erreur de syntaxe.

La seule façon de "sortir" de plusieurs niveaux d'une fonction récursive est de lever une exception. Ce n'est probablement pas idéal pour cette situation; une meilleure option pour votre situation peut être d'utiliser une boucle imbriquée au lieu de la récursivité.

1
duskwuff -inactive- 20 nov. 2018 à 03:52

Une break instruction sera terminer uniquement la boucle en cours, le commutateur ou l'instruction label. Ce n'est pas le bon outil à utiliser pour ce que vous essayez d'accomplir. (Il ne doit pas du tout être utilisé là où vous l'avez, car il est en dehors de l'une de ces constructions.) Une meilleure approche consiste à demander à checkSwitch de renvoyer une valeur indiquant si le processus de correspondance doit être abandonné. Cette valeur peut ensuite remonter la pile de récursivité. Sinon, lancez une exception (que vous devrez ensuite attraper quelque part).

0
Ted Hopp 20 nov. 2018 à 03:51