Question

Après avoir été convaincu que les pauses/continues étiquetées étaient un "non" total ici, j'ai besoin d'aide pour supprimer l'étiquette de mon code.

J'ai une matrice carrée et un vecteur de même longueur.Le vecteur contient déjà quelques valeurs et en fonction des valeurs de la matrice, le vecteur est modifié dans la boucle.

J'espère que le fragment de code est fondamentalement compréhensible…

vectorLoop:
for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) ) continue vectorLoop;

    matrixLoop:
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue matrixLoop;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) continue vectorLoop;
    }
    setValueInVector( v, idx );
}     

S'il vous plaît, convainquez-moi qu'il existe une version plus lisible/meilleure sans les étiquettes.

Était-ce utile?

La solution

En regardant les solutions présentées jusqu'à présent:

  • Ils semblent tous moins lisibles que l'original, dans le sens où ils impliquent de consacrer plus de code au mécanisme du code plutôt qu'à l'algorithme lui-même.

  • Certains d'entre eux sont cassés ou l'étaient avant d'être édités.Le plus accablant est le fait que les gens doivent réfléchir très sérieusement à la manière d'écrire le code sans étiquettes et de ne rien casser.

  • Certains entraînent une pénalité de performances en exécutant deux fois le même test, ce qui n’est pas toujours anodin.L'alternative à cela consiste à stocker et à transmettre des booléens, ce qui devient moche.

  • Refactoriser la partie pertinente du code dans une méthode est en fait une opération inutile :il réorganise la façon dont le code est présenté dans le fichier, mais n'a aucun effet sur la façon dont il est exécuté.

Tout cela me fait croire que, du moins dans le cas de cette question telle que formulée, l'étiquette est la bonne solution et n'a pas besoin d'être remaniée.Il existe certainement des cas où les étiquettes sont utilisées de manière incorrecte et doivent être remaniées.Je ne pense tout simplement pas que cela devrait être traité comme une règle inviolable.

Autres conseils

@Patrick, vous supposez appeler setValueInVector( v, idx );à la fin de la deuxième boucle, c'est OK.Si le code doit être identique, logiquement, il doit être réécrit comme ceci :

for( int idx = 0; idx 

Facilement, mon brave homme.

for( int idx = 0; idx < vectorLength; idx++) {
  if( conditionAtVectorPosition( v, idx ) ) continue;

  for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
    if( anotherConditionAtVector( v, rowIdx ) ) continue;
    if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) break;
  }
  if( !conditionAtMatrixRowCol( m, rowIdx, idx ) )
    setValueInVector( v, idx );
}

MODIFIER:Vous avez tout à fait raison, Anders.J'ai modifié ma solution pour en tenir compte également.

De la lecture de votre code.

  • J'ai remarqué que vous éliminiez les positions vectorielles invalides à conditionAtVectorPosition, puis que vous supprimiez les lignes invalides à anotherConditionAtVector.
  • Il semble que la vérification des lignes sur anotherConditionAtVector soit redondante puisque quelle que soit la valeur de idx, anotherConditionAtVector ne dépend que de l'index de la ligne (en supposant qu'otherConditionAtVector n'ait aucun effet secondaire).

Vous pouvez donc faire ceci :

  • Obtenez d’abord les positions valides en utilisant conditionAtVectorPosition (ce sont les colonnes valides).
  • Ensuite, récupérez les lignes valides en utilisant anotherConditionAtVector.
  • Enfin, utilisez conditionAtMatrixRowCol en utilisant les colonnes et lignes valides.

J'espère que ça aide.

@Nicolas

Certains d'entre eux sont cassés ou l'étaient avant d'être édités.Le plus accablant est le fait que les gens doivent réfléchir à la façon d'écrire le code sans étiquettes et de ne rien casser.

J'ai un autre point de vue :Certains d'entre eux sont brisés car il est difficile de comprendre le comportement de l'algorithme d'origine.

Je me rends compte que c'est subjectif, mais je n'ai aucun mal à lire l'algorithme original.C'est plus court et plus clair que les remplacements proposés.

Toutes les refactorisations de ce fil de discussion émulent le comportement d'une étiquette en utilisant d'autres fonctionnalités de langage - comme si vous portiez le code vers un langage qui n'avait pas d'étiquettes.

Certains entraînent une pénalité de performances en exécutant deux fois le même test, ce qui n’est pas toujours anodin.L'alternative à cela consiste à stocker et à transmettre des booléens, ce qui devient moche.
La pénalité de performance est mineure.Cependant, je suis d'accord que lancer un test deux fois n'est pas une bonne solution.

Je pense que la question était de savoir comment supprimer les étiquettes, et non comment optimiser l'algorithme.Il m'a semblé que l'affiche originale ne savait pas comment utiliser les mots-clés « continuer » et « interrompre » sans étiquettes, mais bien sûr, mes hypothèses peuvent être fausses.

En ce qui concerne les performances, le message ne donne aucune information sur la mise en œuvre des autres fonctions, donc pour autant que je sache, ils pourraient tout aussi bien télécharger les résultats via FTP sous la forme de calculs simples intégrés par le compilateur.

Cela étant dit, faire deux fois le même test n’est pas optimal, en théorie.

MODIFIER:À bien y réfléchir, cet exemple n’est en réalité pas une horrible utilisation des étiquettes.Je suis d'accord que "aller à est un non-non", mais pas à cause d'un code comme celui-ci.L’utilisation d’étiquettes ici n’affecte pas réellement la lisibilité du code de manière significative.Bien sûr, ils ne sont pas obligatoires et peuvent facilement être omis, mais ne pas les utiliser simplement parce que « utiliser des étiquettes est une mauvaise chose » n'est pas un bon argument dans ce cas.Après tout, supprimer les étiquettes ne rend pas le code beaucoup plus facile à lire, comme d'autres l'ont déjà commenté.

Cette question ne concernait pas l'optimisation de l'algorithme - mais merci quand même ;-)

Au moment où je l'ai écrit, je considérais le continu étiqueté comme une solution lisible.

J'ai demandé à SO un question à propos de la convention (avoir l'étiquette en majuscules ou non) pour les étiquettes en Java.

En gros, chaque réponse m'a dit "ne les utilisez pas - il y a toujours une meilleure solution !"refactoriser!".J'ai donc posté cette question pour demander une solution plus lisible (et donc meilleure ?).

Jusqu’à présent, je ne suis pas entièrement convaincu par les alternatives présentées jusqu’à présent.

S'il vous plaît, ne vous méprenez pas.Les étiquettes sont mauvaises la plupart du temps.

Mais dans mon cas, les tests conditionnels sont assez simples et l'algorithme est tiré d'un article mathématique et donc très probablement ne changera pas dans un avenir proche.Je préfère donc avoir toutes les parties pertinentes visibles en même temps au lieu de devoir faire défiler vers une autre méthode nommée quelque chose comme checkMatrixAtRow(x).

Surtout pour les algorithmes mathématiques plus complexes, j'ai du mal à trouver de "bons" noms de fonctions - mais je suppose que c'est encore une autre question

Je pense que les boucles étiquetées sont si rares que vous pouvez choisir la méthode d'étiquetage qui vous convient - ce que vous avez là rend parfaitement claires vos intentions avec la suite.


Après avoir mené la charge pour suggérer de refactoriser les boucles dans la question d'origine et maintenant avoir vu le code en question, je pense que vous avez là une boucle très lisible.

Ce que j'avais imaginé était un morceau de code très différent - en mettant l'exemple réel, je peux voir qu'il est beaucoup plus propre que je ne l'avais pensé.

Mes excuses pour le malentendu.

Est-ce que ça marche pour toi?J'ai extrait la boucle interne dans une méthode CheckedEntireMatrix (vous pouvez la nommer mieux que moi) - De plus, mon Java est un peu rouillé.mais je pense que ça fait passer le message

for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) 
    || !CheckedEntireMatrix(v)) continue;

    setValueInVector( v, idx );
}

private bool CheckedEntireMatrix(Vector v)
{
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }   
    return true;
}

Gishu a la bonne idée :

for( int idx = 0; idx < vectorLength; idx++) {
    if (!conditionAtVectorPosition( v, idx ) 
        && checkedRow(v, idx))
         setValueInVector( v, idx );
}

private boolean checkedRow(Vector v, int idx) {
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }  
    return true;
}

Je ne suis pas trop sûr de comprendre la première suite.Je copierais Gishu et écrirais quelque chose comme ( désolé s'il y a des erreurs ) :

for( int idx = 0; idx < vectorLength; idx++) {
    if( !conditionAtVectorPosition( v, idx ) && CheckedEntireMatrix(v))
        setValueInVector( v, idx );
}

inline bool CheckedEntireMatrix(Vector v) {
    for(rowIdx = 0; rowIdx < n; rowIdx++)
        if ( !anotherConditionAtVector(v,rowIdx) && conditionAtMatrixRowCol(m,rowIdx,idx) ) 
            return false;
    return true;
}

@Sadie:

Ils semblent tous moins lisibles que l'original, dans le sens où ils impliquent de consacrer plus de code au mécanisme du code plutôt qu'à l'algorithme lui-même.

Externaliser la deuxième boucle en dehors de l’algorithme n’est pas forcément moins lisible.Si le nom de la méthode est bien choisi, cela peut améliorer la lisibilité.

Certains d'entre eux sont cassés ou l'étaient avant d'être édités.Le plus accablant est le fait que les gens doivent réfléchir très sérieusement à la manière d'écrire le code sans étiquettes et de ne rien casser.

J'ai un autre point de vue :certains d'entre eux sont défectueux car il est difficile de comprendre le comportement de l'algorithme d'origine.

Certains entraînent une pénalité de performances en exécutant deux fois le même test, ce qui n’est pas toujours anodin.L'alternative à cela consiste à stocker et à transmettre des booléens, ce qui devient moche.

La pénalité de performance est mineure.Cependant, je suis d'accord que lancer un test deux fois n'est pas une bonne solution.

Refactoriser la partie pertinente du code dans une méthode est en fait une opération inutile :il réorganise la façon dont le code est présenté dans le fichier, mais n'a aucun effet sur la façon dont il est exécuté.

Je ne vois pas l'intérêt.Oui, ça ne change pas le comportement, comme...refactoriser ?

Il existe certainement des cas où les étiquettes sont utilisées de manière incorrecte et doivent être remaniées.Je ne pense tout simplement pas que cela devrait être traité comme une règle inviolable.

Je suis entièrement d'accord.Mais comme vous l'avez souligné, certains d'entre nous ont des difficultés à refactoriser cet exemple.Même si l’exemple initial est lisible, il est difficile à maintenir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top