Ci sono dei vantaggi nell'usare questa variabile extra nell'annotazione del ciclo for?

11

Ho trovato la seguente annotazione del ciclo in un grande progetto su cui sto lavorando (pseudocodice):

var someOtherArray = [];
for (var i = 0, n = array.length; i < n; i++) {
    someOtherArray[i] = modifyObjetFromArray(array[i]);
}

Ciò che ha attirato la mia attenzione è questa variabile extra "n". Non ho mai visto un lop scritto in questo modo prima.

Ovviamente in questo scenario non c'è motivo per cui questo codice non possa essere scritto nel modo seguente (che sono molto abituato a):

var someOtherArray = [];
for (var i = 0; i < array.length; i++) {
    someOtherArray[i] = modifyObjetFromArray(array[i]);
}

Ma mi ha fatto pensare.

C'è uno scenario nel momento in cui scrivere un ciclo for potrebbe avere un senso? L'idea mi viene in mente che la lunghezza della "matrice" può cambiare durante l'esecuzione del ciclo for, ma non vogliamo eseguire un ciclo superiore alla dimensione originale, ma non riesco a immaginare un simile scenario.

Ridurre l'array all'interno del loop non ha molto senso, perché è probabile che otteniamo OutOfBoundsException.

Esiste uno schema di progettazione noto in cui questa annotazione è utile?

Modifica Come notato da @ Jerry101, la ragione è la performance. Ecco un link al test delle prestazioni che ho creato: link . A mio parere, la differenza non è abbastanza grande a meno che non si stia procedendo con iterazione attraverso un array molto vasto. Il codice da me copiato ha solo fino a 20 elementi, quindi penso che la leggibilità in questo caso superi la considerazione prestazionale.

    
posta Vlad Spreys 30.01.2015 - 06:24
fonte

4 risposte

27

La variabile n garantisce che il codice generato non recuperi la lunghezza dell'array per ogni iterazione.

È un'ottimizzazione che potrebbe fare la differenza nel tempo di esecuzione a seconda della lingua utilizzata, se l'array è in realtà un oggetto di raccolta o un "array" di JavaScript e altri dettagli di ottimizzazione.

    
risposta data 30.01.2015 - 06:44
fonte
2

Il recupero della lunghezza dell'array può essere facilmente "più costoso" dell'azione effettiva su cui si sta iterando.

Quindi, se il set non cambia, interroga solo la lunghezza una volta.

Non con gli array, ma con i set di record provenienti da un server sql ho visto notevoli miglioramenti non interrogando il numero di record ogni iterazione. (Ovviamente fallo solo se puoi garantire che la matrice o il set di record non vengano modificati durante questo processo).

    
risposta data 30.01.2015 - 09:30
fonte
2

The idea comes to mind that "array" length may change during the for loop execution, but we don't want to loop further than the original size, but I can't imagine such a scenario.

Le persone che parlano di prestazioni sono probabilmente corrette che questo è il motivo per cui è stato scritto in quel modo (la persona che l'ha scritta in quel modo potrebbe non essere corretto che influisce significativamente sulle prestazioni, ma questa è un'altra questione).

Tuttavia, per rispondere a questa parte della tua domanda, penso che sia più probabile che si verifichi quando lo scopo principale del loop è modificare l'array su cui si sta eseguendo il ciclo. Considera qualcosa di simile, in pseudo-codice:

guests = [];
for (i = 0; i < invitations.length; ++i) {
    if (! invitations[i].is_declined()) {
        guests.append(invitations[i].recipient())
    }
}
// maybe some other stuff to modify the guestlist
for (i = 0, n = guests.length; i < n; ++i) {
    if (guests[i].has_plus_one()) {
        guests.append(guests[i].get_plus_one());
    }
}

Naturalmente ci sono altri modi per scriverlo. In questo caso, avrei potuto verificare i più positivi contemporaneamente, controllando se i destinatari accettavano i loro inviti e prodotto l'intero elenco degli invitati un invito alla volta. Non voglio necessariamente combinare queste due operazioni, ma non riesco a pensare immediatamente a una ragione per cui sia decisamente sbagliato e quindi questo disegno è richiesto . È un'opzione da considerare, occasionalmente.

In realtà penso che la cosa più sbagliata di questo codice sia che l'appartenenza alla matrice guests significa cose diverse in punti diversi del codice. Quindi di certo non lo chiamerei un "pattern", ma non so che sia sufficiente un difetto per escludere di fare qualcosa di questo tipo: -)

    
risposta data 30.01.2015 - 15:08
fonte
0

Se possibile, dovresti usare un iteratore che attraversa tutti gli elementi dell'array. Si utilizza l'array solo come una sequenza, non come una memoria ad accesso casuale, quindi sarebbe ovvio che un iteratore che esegue un accesso sequenziale sarebbe più veloce. Immagina cosa pensi che un array sia in realtà un albero binario, ma qualcuno ha scritto un codice che determina la "lunghezza" contando gli elementi e il codice che accede all'elemento i-esimo, attraversando l'elemento, ciascuno in O (n ). Un iteratore può essere molto veloce, il tuo loop sarà sloooooow.

    
risposta data 17.04.2017 - 14:06
fonte

Leggi altre domande sui tag