Modo chiaro per saltare il primo elemento in un indice basato su loop


9

Ho un ciclo for in cui devo saltare il primo elemento in un array a base zero.

Quale di questi mostra le mie intenzioni più chiaramente?

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

o

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

28
$i=2-1è il modo migliore. : /
yannis,

7
Probabilmente sceglierei la prima opzione e aggiungerei un commento per spiegare perché il primo elemento deve essere ignorato.
Vincent Savard,

3
La chiarezza è ciò a cui sto puntando, ho modificato la domanda. È più chiaro?
Tomas Zubiri,

10
Non usare PHP è il modo migliore.
gatto

3
PHP ha un costrutto foreach? Potresti fare foreach ($i in range(1, count))(qualunque cosa assomigli a PHP). O qualcosa del genere foreach ($item in array.skip(1))è ciò che farebbe una persona C #.
usr

Risposte:


23

Odio entrambi.

Chi ha detto che potresti usare numeri magici? Se inizi con un offset di 1, che ne dici di dirci PERCHÉ stai iniziando con un offset di 1. Aggiungere uno zero ugualmente magico non mi spiega nulla.

È questo l'offset del payload? È una stringa pasquale che stai convertendo in una stringa c terminata con null? Per favore, dicci cosa sta succedendo.

Mi dispiace, ma ho sprecato gran parte della mia carriera decodificando misteri inutili come questo e la mia pazienza per loro si è esaurita. È una variabile con un nome decente davvero molto da chiedere?

Per nome decente intendo un nome che spiega PERCHÉ stiamo saltando il primo elemento. Non qualcosa che dice semplicemente CHE stiamo saltando il primo elemento. L'1 me lo ha detto da solo.


20
0 e 1 non sono numeri magici.
user949300,

19
@ user949300 Oh, certamente sono qui. Sono semplicemente numeri che a volte non sono magici. Solo perché 2 è sempre un numero magico non significa che 1 non sia mai un numero magico. La magia deriva dal significato mancante. Cosa diavolo significa partire da un offset 1 qui? A che serve aggiungere uno 0 qui? Oh sì, questi numeri sono certamente magici qui. Vedo la polvere dei folletti che si stacca da loro.
candied_orange,

4
Certo, inizierò a definire static final int LONELIEST_NUMBER = 1in tutto il mio codice Java. :-) Detto questo, a pensarci bene mi piacerebbe annullare la votazione della tua risposta, ma non posso a meno che non la modifichi. Regola così sciocca?
user949300,

6
@Eiko: se non vi è alcuna spiegazione del motivo per cui il ciclo inizia dal secondo elemento, è praticamente garantito che alcuni programmatori di manutenzione cambieranno il ciclo per iniziare dal primo elemento. Ecco perché il numero 1 è un numero magico in questo contesto.
Bart van Ingen Schenau,

2
@BartvanIngenSchenau Ho pensato che ci sarebbe stata una ragione immediatamente visibile nel contesto. Mi piace confrontare gli elementi con i loro predecessori (che ho pensato essere il caso d'uso più frequente per iniziare da 1 - e non riesco a vedere alcun nome di costante utile qui). Se il primo elemento ha un significato ultra-speciale, il design potrebbe essere rotto e dovrebbero esserci correzioni migliori rispetto alla denominazione di tale indice. Non dico che non c'è mai motivo di introdurre una variabile qui. È solo che penso che quei casi siano (o forse dovrebbero essere solo) molto rari.
Eiko

12

Risposta breve: la prima opzione è migliore.

La seconda opzione aggiunge solo rumore. È molto improbabile che 0 + 1 aiuti il ​​lettore a capire che avrebbe potuto essere 0 ma è 1. Molto più probabilmente sarà perplesso per un breve momento e distratto da ciò che riguarda il loop. Soprattutto in una lingua in cui tutte le matrici iniziano da 0.

Come altri menzionato, se si desidera sottolineare il fatto che il ciclo inizia da 1, non da 0, è sufficiente aggiungere un commento.


10

Non dirci che stai saltando il primo oggetto: possiamo vederlo. Ciò che non è ovvio è il perché . Quindi .. se non è ovvio dal contesto, dicci perché:

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

Oppure, se sei contrario ai commenti, qualcosa del tipo:

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

Non usare commenti e trucchi per ricordarci come funziona la lingua.


6

Il tuo esempio sembra inventato. Nel codice del mondo reale, il fatto che i loop debbano iniziare dal secondo elemento dell'array è molto probabilmente evidente dalle seguenti righe di codice. Ad esempio, se il codice reale appare così

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

non ci sarebbe alcuna spiegazione o costrutto "0 + 1" necessario per chiarire perché il ciclo inizia da 1 anziché 0.

Tuttavia, se il codice all'interno del ciclo non spiega i motivi in ​​modo così ovvio (forse array[0]ha un significato speciale e deve essere trattato in modo diverso rispetto agli elementi rimanenti), quindi aggiungere un commento esplicativo. Ma prima di farlo, pensa due volte se puoi evitare di avere array[0]questo significato speciale e riorganizza il codice circostante, che probabilmente sarebbe la migliore alternativa.


In situazioni come il tuo codice di esempio, mi piace nominare le variabili "oneBasedIndex" o "zeroBasedIndex". Anche se qualcosa di ancora più specifico per quel compito sarebbe meglio.
user949300,

5

Non ho mai visto l'opzione n. 2, ma mi piace. Perché? Con l'opzione n. 1 mi chiedo se il programmatore abbia dimenticato che le matrici iniziano da 0. L'opzione n. 2 chiarisce che stanno deliberatamente iniziando da 1.

Detto questo, meglio in entrambi i casi aggiungere un commento sul motivo per cui stai saltando l'elemento.

Oppure, se riesci a descrivere facilmente perché stai iniziando da uno, usa una costante. Ad esempio, se si esaminano gli argomenti della riga di comando, qualcosa del genere

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

Personalmente, probabilmente userei solo un commento, YMMV.


Dirò che al di fuori degli ambienti in cui hai a che fare con i principianti, non ho mai avuto il problema dei colleghi che dimenticano che le matrici iniziano da zero. Potrei vederlo accadere se il tuo lavoro usasse anche un linguaggio come MATLAB, ma nella maggior parte degli ambienti, suppongo che il programmatore sapesse cosa stavano facendo. E diamine, iniziare un loop su 1 è dannatamente comune. Ci sono alcuni motivi per saltare il primo elemento di qualcosa.
Kat

@Kat Questo motivo deve essere chiaro per i futuri lettori. Preferirei presumere che un futuro programmatore non sappia cosa sta facendo.
A1rPun,

2

Dubito che qualcuno sarebbe confuso dal primo. Abbiamo dovuto farlo tutti. Tanto che è molto più probabile che il secondo confonda. "Perché c'è uno 0+ lì? Hanno in qualche modo ignorato l'operatore +?"

Un compilatore decente trasformerà comunque il secondo nel primo, ma sembra che tu stia usando PHP, che viene interpretato. Quindi ogni volta che l'interprete raggiunge quel loop, dovrà effettivamente aggiungere 0 e 1. Non è un grosso problema, ma perché fare in modo che l'interprete faccia il lavoro?


2

Utilizzare una variabile che spiega il punto iniziale.

Devi " saltare il primo elemento in un array a base zero ", quindi ad esempio:

skipFirstElement = 1;

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

6
Mi piace usare una variabile ma odio questo nome. Non spiega PERCHÉ stai saltando il primo elemento. A 1 me lo dice comunque. A che serve una variabile che deve essere rinominata quando cambia valore? So che l'OP non ci ha dato alcuna idea del perché, quindi per scegliere un buon nome dovrai inventarti un motivo. Senza un nome migliore preferirei avere l'1 di nuovo.
candied_orange,

@CandiedOrange Sono d'accordo con te sul fatto che il nome della variabile dovrebbe essere più significativo, ma il problema quando viene presentato non spiega perché vuole saltare il primo valore. Il mio punto è, faccio solo un esempio, l'autore può scegliere un nome che è meglio per lui.
catta,

Per favore, non insegnare in questo modo. Questo è abbastanza confuso. A molti programmatori raggiungeranno il nome più semplice possibile in modo che possano tornare a scrivere codice difficile da capire. Seriamente, preferirei affrontare l'1 piuttosto che questo.
candied_orange,

1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Se uno è ossessivo con tutti i loop che iniziano da zero, è possibile utilizzare un'istruzione continue. Aggiungi un commento al motivo per cui stai saltando poiché normalmente non lo faresti.


2
Il problema con questa opzione significa che lo valuteremo per ogni singolo elemento, aggiungendo n ulteriori confronti al loop, semplicemente saltando il primo attraverso qualche altro metodo (spostando l'array, iniziando con i = 1, qualunque cosa ) significa solo fare il lavoro necessario.
Kevin Fee,

3
@KevinFee Se non hai a che fare con array di grandi dimensioni, direi che questo semplice confronto non sarà un problema. E mi piace molto l'espressione di if first then skipun commento che dice perché. Ancora senza contesto nessuna delle soluzioni è "migliore"
Ivan Pintar,

-2

Quello che farei è rimuovere il primo elemento prima di eseguire il looping. Crea un nuovo array, se necessario. Spiega in un commento perché lo stai facendo. E poi fai una semplice ricerca.

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

In questo modo il tuo intento è perfettamente chiaro.

Per chiarire ulteriormente è possibile racchiudere il codice in un metodo con un nome appropriato per rendere le cose più chiare.

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

Tuttavia tutto ciò manca ancora del contesto. Cosa vuoi fare con gli elementi? Restituirai il nuovo array? Ti interessa l'originale e il nuovo array dopo di te doStuff()?

Comunque, non c'è una risposta chiara qui, e decidere come rendere il codice leggibile dipende molto dal contesto.


1
Mi piace perché non ho bisogno di gestire gli indici ora, il che è sempre un vantaggio.
Tomas Zubiri,

1
Lo svantaggio qui è che se non si desidera effetti collaterali, è necessario copiare l'intero array.
Tomas Zubiri,

1
E se il motivo per cui iniziamo da 1 è perché stiamo facendo $array[$i-1] = $array[$i]qualcosa di simile, come nella risposta di @ DocBrown?
Kevin Fee,

1
Questo mi sembra orribile. Oltre a tutta l'inefficienza, gli effetti collaterali e l'incapacità di risolvere casi d'uso abbastanza comuni per 1(vedi il commento di Kevin Lee), non rende affatto più chiaro il codice. Il lettore deve capire array_shift, cosa fa, come funziona. Forse questa riga di codice è un bug? Modifica l'array o ne restituisce uno nuovo? Inserisce un elemento o ne rimuove uno? Cambia gli indici o no? Non riesco a vedere come l'uso di un ciclo basato su una sola base non sarebbe un enorme miglioramento in quella funzione (e dato il suo nome, immediatamente comprensibile).
Eiko

1
Le risposte a queste domande dipendono fortemente dal contesto. E per quanto riguarda l'efficienza, mi occuperei di ogni giorno ... Qualsiasi differenza di prestazione è quasi invisibile nella maggior parte dei casi.
Ivan Pintar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.