Ancora giocando con le tendenze di Twitter. Ho abbastanza dati raccolti che vorrei velocizzare l'elaborazione. Voglio assegnare un indice intero a ciascuna parola di tendenza utilizzando un array associativo indicizzato con la parola di tendenza. Di seguito sono riportate tre tecniche per aggiungere una nuova parola alla tabella o per ottenere l'indice di una vecchia parola.
Il primo utilizza TRY per catturare l'eccezione quando una parola non è nella tabella. È il più veloce se la parola è presente e il più lento (di gran lunga) se si verifica l'eccezione.
Il secondo usa CONTAINS per verificare se la parola è presente, quindi la somma o la cerca. È il più veloce per aggiungere e il più lento per cercare (perché cerca due volte).
L'ultimo utilizza un valore predefinito di matrice associativa per vedere se il valore recuperato esiste già. Fornisce una buona velocità di compromesso.
Tutti gli esempi hanno un ciclo "t" che viene eseguito due volte. La prima volta che l'array xN è vuoto e deve essere compilato. La seconda volta tutti i valori saranno già presenti.
// Three ways to build a lookup table. No clear winner!
// Goal: assign an integer, starting at 1, to each new
// entry. For timing purposes, use the integer as the
// key and the value. The key will be a string in real
// code. The value will be used as an index elsewhere.
explain = {"create new entry","use existing entry"};
N = 1e5; // several seconds at 1e5
/*
Use TRY to determine when an entry needs to be created.
On the "catch" create the entry. If there is no catch,
the value is already fetched. The "t" loop runs 20X
slower the first time because the "catch" is expensive.
But the second time the "t" loop is the fastest solution.
*/
x1 = [=> ];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
Try( y = x1[ix], y = (x1[ix] = ix) )
);
stop = HP Time();
Write( Eval Insert( "\!nTry method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
/*
Use CONTAINS to determine if the entry needs to be created.
Use the if's "then" clause to fetch the existing index or
"else" clause to create a new entry. The "t" loop has the
fastest speed on the first run, by far, and the slowest
speed on the second run.
*/
x2 = [=> ];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
If( Contains( x2, ix ),
y = x2[ix],
y = (x2[ix] = ix)
)
);
stop = HP Time();
Write( Eval Insert( "\!nContains method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
/*
Use a DEFAULT value to determine if the entry needs to be
created. Fetch the value for the entry, check for the default
and create if needed. This gives an between value for both
"t" loops. It might be a good compromise choice if no extra
testing will be done and 0 can be used as a default. !y,
below, is faster than y==0.
*/
x3 = [=> 0];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
y = x3[ix];
If( !y, y = (x3[ix] = ix) );
);
stop = HP Time();
Write( Eval Insert( "\!ndefault 0 method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
// quick test... the lack of a default value in x1 and x2
// makes them compare not equal, so add it before testing.
x1 << setdefaultvalue( 0 );
x2 << setdefaultvalue( 0 );
Show( x1 == x2, x1 == x3 );
Metodo di prova: 2.851 secondi crea una nuova voce
Metodo di prova: 0,099 secondi usa la voce esistente
Contiene il metodo: 0.209 secondi crea una nuova voce
Contiene il metodo: 0,151 secondi usa la voce esistente
metodo predefinito 0: 0,259 secondi crea una nuova voce
metodo predefinito 0: 0.117 secondi usa la voce esistente
x1 == x2 = 1;
x1 == x3 = 1;
In rosso, TRY e CONTAINS forniscono i tempi più veloci per voci esistenti e nuove. In verde, DEFAULT 0 potrebbe essere un buon compromesso. Dipende davvero da quante voci verranno create e quante volte verranno cercate.
Grazie del promemoria! Ho scelto un valore predefinito al di fuori dell'insieme di valori consentiti per il mio esempio, quindi non molto utile come valore predefinito. Zero è un indice non valido per la mia ricerca. Ho iniziato con missing, ma isMissing(x) è più costoso di x==0.
Attualmente sto lavorando su alcune cose dell'API REST e per questo motivo Array associativi e rimozione di chiavi con valore uguale al valore predefinito Devo/eviterò di utilizzare i valori predefiniti. Il motivo è che utilizzo la risposta JSON per creare un'interfaccia utente interattiva per gli utenti JMP e ho bisogno delle chiavi anche se hanno "valore predefinito". Ma penso che smetterò di usare l'opzione pigra di usare Prova a verificare la presenza di chiavi mancanti dopo questo post.
Visualizza altro...