Forma clara de omitir el primer elemento en un índice basado en el bucle

9

Tengo un bucle for donde debo omitir el primer elemento en una matriz basada en cero.

¿Cuál de estos muestra mis intenciones más claramente?

for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

o

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}
Tomás Zubiri
fuente
28
Tampoco, $i=2-1es el camino superior. : /
yannis
77
Probablemente elegiría la primera opción y agregaría un comentario para explicar por qué se debe omitir el primer elemento.
Vincent Savard
3
La claridad es lo que busco, edité la pregunta. ¿Eso está más claro?
Tomas Zubiri
10
No usar PHP es la forma superior.
gato
3
¿PHP tiene una construcción foreach? Podrías hacer foreach ($i in range(1, count))(lo que sea que se vea en PHP). O algo así como foreach ($item in array.skip(1))lo que haría una persona de C #.
Usr

Respuestas:

23

Odio a los dos.

¿Quién dijo que podrías usar números mágicos? Si va a comenzar con un desplazamiento de 1, ¿qué tal si nos dice POR QUÉ está comenzando con un desplazamiento de 1. Agregar un cero igualmente mágico no me explica nada.

¿Es este el desplazamiento de la carga útil? ¿Es esta una cadena pascal que está convirtiendo en una cadena c terminada en nulo? Por favor dinos qué está pasando.

Lo siento, pero he desperdiciado gran parte de mi carrera descifrando misterios sin sentido como este y mi paciencia por ellos se ha agotado. ¿Es una variable con un nombre decente realmente mucho pedir?

Por nombre decente me refiero a un nombre que explica POR QUÉ estamos omitiendo el primer elemento. No es algo que simplemente diga que estamos omitiendo el primer elemento. El 1 me dijo que por sí solo.

naranja confitada
fuente
19
0 y 1 no son números mágicos.
user949300
19
@ user949300 Oh, ciertamente están aquí. Son simplemente números que ocasionalmente no son mágicos. El hecho de que 2 sea siempre un número mágico no significa que 1 nunca sea un número mágico. La magia proviene del significado perdido. ¿Qué diablos significa comenzar con un desplazamiento de 1 aquí? ¿De qué sirve agregar un 0 aquí? Oh, sí, estos números son ciertamente mágicos aquí. Puedo ver el polvo de duendecillo goteando de ellos.
candied_orange
44
Claro, comenzaré a definir static final int LONELIEST_NUMBER = 1en todo mi código Java. :-) Dicho esto, pensándolo bien, me gustaría anular la votación de su respuesta, pero no puedo a menos que la edite. ¿Tan tonta regla?
user949300
66
@Eiko: Si no hay una explicación de por qué el ciclo comienza en el segundo elemento, está prácticamente garantizado que algún programador de mantenimiento cambiará el ciclo para comenzar en el primer elemento. Es por eso que el número 1 es un número mágico en este contexto.
Bart van Ingen Schenau
2
@BartvanIngenSchenau Supuse que habría una razón inmediatamente visible dentro del contexto. Como comparar elementos con sus predecesores (que pensé que era el caso de uso más frecuente para comenzar en 1, y no veo ningún nombre constante útil aquí). Si el primer elemento tiene un significado ultra especial, el diseño podría estar roto y debería haber mejores soluciones que nombrar ese índice. No digo que nunca haya una razón para introducir una variable aquí. Es solo que creo que esos casos son (o quizás solo deberían ser) muy raros.
Eiko
12

Respuesta corta: la primera opción es mejor.

La segunda opción solo agrega ruido. Es muy poco probable que 0 + 1 ayude al lector a comprender que podría haber sido 0, pero es 1. Es mucho más probable que se desconcierte un momento y se distraiga de lo que trata el ciclo. Especialmente en un lenguaje donde todas las matrices comienzan en 0.

Como se mencionó anteriormente, si desea enfatizar el hecho de que el ciclo comienza desde 1, no desde 0, simplemente agregue un comentario.

Florian F
fuente
10

No nos digas que te estás saltando el primer elemento, podemos ver eso. Lo que no es obvio es por qué . Entonces ... si no es obvio por el contexto, dinos por qué:

// array[0] is just a header
for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

O, si eres reacio a los comentarios, algo como:

$lastHeaderIndex = 0;
for($i = $lastHeaderIndex + 1 ; $i < count(array) ; $i++){
    array[$i];
}

No use comentarios y trucos para recordarnos cómo funciona el lenguaje.

svidgen
fuente
6

Tu ejemplo parece artificial. En el código del mundo real, el hecho de que los bucles deben comenzar en el segundo elemento de matriz es probablemente obvio en las siguientes líneas de código. Por ejemplo, si el código real se ve así

for($i=1 ; $i < count(array) ; $i++){
    array[$i-1]=array[$i];
}

no habría explicación o construcción "0 + 1" necesaria para aclarar por qué el ciclo comienza en 1 en lugar de 0.

Sin embargo, si el código dentro del bucle no explica las razones de una manera tan obvia (tal vez array[0]tiene un significado especial y debe tratarse de manera diferente a los elementos restantes), entonces agregue un comentario explicativo. Pero antes de hacer esto, piense dos veces si puede evitar tener array[0]este significado especial y reorganice el código circundante, que probablemente sería la mejor alternativa.

Doc Brown
fuente
En situaciones como su código de ejemplo, me gusta nombrar las variables "oneBasedIndex" o "zeroBasedIndex". Aunque algo aún más específico para esa tarea sería mejor.
user949300
5

Nunca vi la opción # 2, pero me gusta. ¿Por qué? Con la opción n. ° 1, me pregunto si el programador olvidó que las matrices comienzan en 0. La opción n. ° 2 aclara que están comenzando deliberadamente en 1.

Dicho esto, lo mejor en cualquier caso es agregar un comentario por qué está omitiendo el elemento.

O, si puede describir fácilmente por qué está comenzando en uno, use una constante. Por ejemplo, si observa los argumentos de la línea de comandos, algo como

define ('FIRST_REAL_ARGUMENT', 1);
for ($i=FIRST_REAL_ARGUMENT; ...)

Personalmente, probablemente solo usaría un comentario, YMMV.

user949300
fuente
Diré que fuera de los entornos donde se trata con principiantes, nunca he tenido el problema de que los compañeros de trabajo olviden que las matrices comienzan en cero. Podría ver que sucediera si su trabajo también usara un lenguaje como MATLAB, pero en la mayoría de los entornos, supondría que el programador sabía lo que estaban haciendo. Y diablos, comenzar un ciclo en 1 es bastante común. Hay bastantes razones para omitir el primer elemento de algo.
Kat
@Kat Esa razón debe ser clara para los futuros lectores. Prefiero asumir que un futuro programador no sabe lo que está haciendo.
A1rPun
2

Dudo que alguien se confunda con el primero. Todos hemos tenido que hacerlo. Tanto es así que es mucho más probable que el segundo confunda. "¿Por qué hay un 0+ allí? ¿Anularon el operador + de alguna manera?"

Un compilador decente convertirá el segundo en el primero de todos modos, pero parece que estás usando PHP, que se interpreta. Entonces, cada vez que el intérprete llegue a ese ciclo, tendrá que agregar 0 y 1. No es gran cosa, pero ¿por qué hacer que el intérprete haga el trabajo?

Kevin Fee
fuente
2

Use una variable que explique el punto de inicio.

Debe " omitir el primer elemento en una matriz basada en cero ", por ejemplo:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}
catta
fuente
66
Me gusta usar una variable pero odio este nombre. No explica POR QUÉ te estás saltando el primer elemento. Un 1 me dice eso de todos modos. ¿De qué sirve una variable que necesita ser renombrada cuando cambia su valor? Sé que el OP no nos dio idea de por qué, así que para elegir un buen nombre tendrás que inventar una razón. Sin un nombre mejor, preferiría recuperar el 1.
candied_orange
@CandiedOrange Estoy de acuerdo con usted en que el nombre de la variable debería ser más significativo, pero el problema tal como se presenta no explica por qué quiere omitir el primer valor. Mi punto es, solo doy un ejemplo, el autor puede elegir el nombre que sea mejor para él.
catta
Por favor no enseñe de esta manera. Esto es bastante confuso. Muchos codificadores buscarán el nombre más fácil que puedan para que puedan volver a escribir código difícil de entender. En serio, prefiero tratar con el 1 que con esto.
candied_orange
1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Si uno está obsesivo con todos los bucles que comienzan en cero, podría usar una declaración de continuación. Agregue un comentario sobre por qué está omitiendo, ya que normalmente uno no lo haría.

Jon Raynor
fuente
2
El problema con esta opción significa que vamos a evaluar esto para cada elemento individual, agregando n comparaciones adicionales al ciclo, mientras simplemente omitimos el primero a través de algún otro método (cambiando la matriz, comenzando con i = 1, lo que sea ) significa solo hacer el trabajo que necesita.
Kevin Fee
3
@KevinFee Si no se trata de matrices masivas, diría que esta comparación simple no será un problema. Y me gusta bastante lo explícito if first then skipcon un comentario que dice por qué. Aún sin contexto, ninguna de las soluciones es "mejor"
Ivan Pintar
-2

Lo que haría es eliminar el primer elemento antes de repetir. Cree una nueva matriz si es necesario. Explica en un comentario por qué lo estás haciendo. Y luego haz un simple foreach.

$arrayCopy = $array; // in case you don't want to touch the original array
array_shift($arrayCopy); // removing first element because of X reason.
foreach($arrayCopy => $element) { 
    // do stuff
}

De esta manera tu intención es perfectamente clara.

Para aclarar más, podría envolver el código en un método con un nombre apropiado para aclarar las cosas.

function doStuffToAllButTheFirst($array) { // this copies the original array, so there are no sideffects
    array_shift($array);
    foreach($array => $element) { // do stuff }  
}

Sin embargo, a todo esto todavía le falta contexto. ¿Qué quieres hacer con los elementos? ¿Volverá la nueva matriz? ¿Te importa el original y el nuevo conjunto después de ti doStuff()?

De todos modos, no hay una respuesta clara aquí, y decidir cómo hacer que el código sea legible depende en gran medida del contexto.

Ivan Pintar
fuente
1
Me gusta esto porque no necesito lidiar con índices ahora, lo cual siempre es una ventaja.
Tomas Zubiri
1
La desventaja aquí es que si no desea efectos secundarios, debe copiar toda la matriz.
Tomas Zubiri
1
¿Y qué pasa si la razón por la que comenzamos en 1 es porque estamos haciendo $array[$i-1] = $array[$i]o algo similar, según la respuesta de @ DocBrown?
Kevin Fee
1
Esto me parece horrible. Además de toda la ineficiencia, los efectos secundarios y la incapacidad para resolver casos de uso bastante comunes 1(ver el comentario de Kevin Lee), no hace que el código sea más claro. El lector debe comprender array_shift, qué hace, cómo funciona. ¿Quizás esta línea de código es un error? ¿Modifica la matriz o devuelve una nueva? ¿Inserta un elemento o elimina uno? ¿Cambia los índices o no? No veo cómo usar un bucle basado en uno no sería una gran mejora en esa función (y dado su nombre, comprensible al instante).
Eiko
1
Las respuestas a estas preguntas dependen en gran medida del contexto. Y en cuanto a la eficiencia, preferiría cualquier día ... Cualquier diferencia de rendimiento es casi invisible en la mayoría de los casos.
Ivan Pintar