Pregunta

Después de que me convencí de que las pausas/continuaciones etiquetadas son un total "nono" sobre aquí, necesito ayuda para quitar la etiqueta de mi código.

Tengo una matriz cuadrada y un vector que tiene la misma longitud.El vector ya tiene algunos valores y, dependiendo de los valores de la matriz, el vector cambia en el bucle.

Espero que el fragmento de código sea básicamente comprensible...

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

Por favor, convénceme de que existe una versión mejor y más legible sin las etiquetas.

¿Fue útil?

Solución

Mirando las soluciones presentadas hasta ahora:

  • Todos parecen menos legibles que el original, ya que implican gastar más código en el mecanismo del código que en el algoritmo en sí.

  • Algunos de ellos están rotos o lo estaban antes de ser editados.Lo más condenatorio es el hecho de que la gente tiene que pensar mucho sobre cómo escribir el código sin etiquetas y sin romper nada.

  • Algunos vienen con una penalización de rendimiento al ejecutar la misma prueba dos veces, lo que no siempre es trivial.La alternativa a esto es almacenar y pasar valores booleanos, lo que se pone feo.

  • Refactorizar la parte relevante del código en un método es efectivamente una operación no operativa:reorganiza la forma en que se presenta el código en el archivo, pero no tiene ningún efecto en la forma en que se ejecuta.

Todo lo cual me hace creer que, al menos en el caso de esta pregunta tal como está formulada, la etiqueta es la solución correcta y no es necesario refactorizarla.Ciertamente, hay casos en los que las etiquetas se usan incorrectamente y deben refactorizarse.Simplemente no creo que deba tratarse como una regla inquebrantable.

Otros consejos

@Patrick, estás asumiendo que llamas a setValueInVector( v, idx );al final del segundo ciclo está bien.Si el código va a ser idéntico, lógicamente, debe reescribirse en algo como esto:

for( int idx = 0; idx 

Fácilmente, mi buen hombre.

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

EDITAR:Tienes toda la razón, Anders.Edité mi solución para tener eso en cuenta también.

De leer tu código.

  • Noté que eliminaste las posiciones de vectores no válidas en conditionAtVectorPosition y luego eliminas las filas no válidas en anotherConditionAtVector.
  • Parece que verificar filas en anotherConditionAtVector es redundante ya que cualquiera que sea el valor de idx, anotherConditionAtVector solo depende del índice de la fila (suponiendo que anotherConditionAtVector no tenga efectos secundarios).

Entonces puedes hacer esto:

  • Obtenga primero las posiciones válidas usando conditionAtVectorPosition (estas son las columnas válidas).
  • Luego obtenga las filas válidas usando anotherConditionAtVector.
  • Finalmente, use conditionAtMatrixRowCol usando las columnas y filas válidas.

Espero que esto ayude.

@Nicolás

Algunos de ellos están rotos o lo estaban antes de ser editados.Lo más condenable es el hecho de que la gente tiene que pensar mucho acerca de cómo escribir el código sin etiquetas y no romper cualquier cosa.

Tengo un punto de vista diferente:algunos de ellos están rotos porque es difícil de entender el comportamiento del algoritmo original.

Me doy cuenta de que es subjetivo, pero no tengo problemas para leer el algoritmo original.Es más breve y claro que los reemplazos propuestos.

Lo que hacen todas las refactorizaciones en este hilo es emular el comportamiento de una etiqueta usando otras características del lenguaje, como si estuvieras transfiriendo el código a un lenguaje que no tuviera etiquetas.

Algunos vienen con una penalización de rendimiento al ejecutar la misma prueba dos veces, lo que no siempre es trivial.La alternativa a esto es almacenar y pasar valores booleanos, lo que se pone feo.
La penalización por desempeño es menor.Sin embargo, estoy de acuerdo en que ejecutar una prueba dos veces no es una buena solución.

Creo que la pregunta era cómo eliminar las etiquetas, no cómo optimizar el algoritmo.Me pareció que el autor original no sabía cómo utilizar las palabras clave "continuar" y "interrumpir" sin etiquetas, pero, por supuesto, mis suposiciones pueden estar equivocadas.

Cuando se trata de rendimiento, la publicación no brinda ninguna información sobre la implementación de las otras funciones, por lo que, por lo que sé, también podrían descargar los resultados a través de FTP como si consistieran en cálculos simples incorporados por el compilador.

Dicho esto, hacer la misma prueba dos veces no es lo óptimo, en teoría.

EDITAR:Pensándolo bien, el ejemplo en realidad no es un uso horrible de etiquetas.Estoy de acuerdo que "ir a no-no", pero no por un código como este.El uso de etiquetas aquí en realidad no afecta la legibilidad del código de manera significativa.Por supuesto, no son obligatorias y pueden omitirse fácilmente, pero no usarlas simplemente porque "usar etiquetas es malo" no es un buen argumento en este caso.Después de todo, eliminar las etiquetas no hace que el código sea mucho más fácil de leer, como ya han comentado otros.

Esta pregunta no trataba sobre la optimización del algoritmo, pero gracias de todos modos ;-)

En el momento en que lo escribí, consideré la etiqueta continuar como una solución legible.

Le pregunté entonces a pregunta sobre la convención (tener la etiqueta en mayúsculas o no) para etiquetas en Java.

Básicamente, cada respuesta me decía "no los uses, ¡siempre hay una manera mejor!¡refactorizar!".Así que publiqué esta pregunta para solicitar una solución más legible (¿y por lo tanto mejor?).

Hasta ahora, las alternativas presentadas hasta ahora no me convencen del todo.

Por favor, no me malinterpretes.Las etiquetas son malas la mayor parte del tiempo.

Pero en mi caso, las pruebas condicionales son bastante simples y el algoritmo se tomó de un artículo matemático y, por lo tanto, es muy probable que no cambie en el futuro cercano.Así que prefiero tener todas las partes relevantes visibles a la vez en lugar de tener que desplazarme a otro método llamado algo así como checkMatrixAtRow(x).

Especialmente en algoritmos matemáticos más complejos, me resulta bastante difícil encontrar nombres de funciones "buenos", pero supongo que esa es otra cuestión más.

Creo que los bucles etiquetados son tan poco comunes que puedes elegir cualquier método de etiquetado que funcione para ti; lo que tienes ahí deja perfectamente claras tus intenciones con las continuas.


Después de liderar la carga para sugerir refactorizar los bucles en la pregunta original y ahora ver el código en cuestión, creo que tienes un bucle muy legible allí.

Lo que había imaginado era un fragmento de código muy diferente; al poner el ejemplo real, puedo ver que es mucho más limpio de lo que había pensado.

Mis disculpas por el malentendido.

¿Esto funciona para tí?Extraje el bucle interno en un método CheckedEntireMatrix (puedes nombrarlo mejor que yo). Además, mi Java está un poco oxidado.pero creo que transmite el mensaje

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 tiene la idea correcta:

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

No estoy muy seguro de entender la primera continuación.Copiaría a Gishu y escribiría algo como (lo siento si hay algunos errores):

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:

Todos parecen menos legibles que el original, ya que implican gastar más código en el mecanismo del código que en el algoritmo en sí.

Externalizar el segundo bucle fuera del algoritmo no es necesariamente menos legible.Si el nombre del método se elige bien, puede mejorar la legibilidad.

Algunos de ellos están rotos o lo estaban antes de ser editados.Lo más condenatorio es el hecho de que la gente tiene que pensar mucho sobre cómo escribir el código sin etiquetas y sin romper nada.

Tengo un punto de vista diferente:algunos de ellos están rotos porque es difícil entender el comportamiento del algoritmo original.

Algunos vienen con una penalización de rendimiento al ejecutar la misma prueba dos veces, lo que no siempre es trivial.La alternativa a esto es almacenar y pasar valores booleanos, lo que se pone feo.

La penalización por desempeño es menor.Sin embargo, estoy de acuerdo en que ejecutar una prueba dos veces no es una buena solución.

Refactorizar la parte relevante del código en un método es efectivamente una operación no operativa:reorganiza la forma en que se presenta el código en el archivo, pero no tiene ningún efecto en la forma en que se ejecuta.

No veo el punto.Sí, no cambia el comportamiento, como...refactorización?

Ciertamente, hay casos en los que las etiquetas se usan incorrectamente y deben refactorizarse.Simplemente no creo que deba tratarse como una regla inquebrantable.

Estoy totalmente de acuerdo.Pero como ha señalado, algunos de nosotros tenemos dificultades al refactorizar este ejemplo.Incluso si el ejemplo inicial es legible, es difícil de mantener.

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