Spiele immer noch mit Twitter-Trends. Ich habe genug Daten gesammelt, sodass ich die Verarbeitung beschleunigen möchte. Ich möchte jedem Trendwort einen ganzzahligen Index zuweisen, indem ich ein assoziatives Array verwende, das mit dem Trendwort indiziert ist. Nachfolgend finden Sie drei Techniken, um ein neues Wort zur Tabelle hinzuzufügen oder den Index für ein altes Wort zu erhalten.
Der erste verwendet TRY, um die Ausnahme abzufangen, wenn ein Wort nicht in der Tabelle enthalten ist. Es ist am schnellsten, wenn das Wort vorhanden ist, und am langsamsten (bei weitem), wenn die Ausnahme auftritt.
Die zweite verwendet CONTAINS, um zu testen, ob das Wort vorhanden ist, fügt es dann hinzu oder schlägt es nach. Es ist am schnellsten zum Hinzufügen und am langsamsten zum Nachschlagen (weil es zweimal nachschlägt).
Der letzte verwendet einen assoziativen Array-Standardwert, um zu sehen, ob der abgerufene Wert bereits vorhanden ist. Es bietet eine schöne Kompromissgeschwindigkeit.
Alle Beispiele haben eine "t"-Schleife, die zweimal ausgeführt wird. Beim ersten Mal ist das xN-Array leer und muss ausgefüllt werden. Beim zweiten Mal sind alle Werte bereits vorhanden.
// 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 );
Try-Methode: 2.851 Sekunden Neuen Eintrag erstellen
Versuchsmethode: 0,099 Sekunden vorhandenen Eintrag verwenden
Enthält Methode: 0,209 Sekunden neuen Eintrag erstellen
Enthält Methode: 0,151 Sekunden vorhandenen Eintrag verwenden
Standard 0 Methode: 0,259 Sekunden neuen Eintrag erstellen
Standard 0 Methode: 0,117 Sekunden vorhandenen Eintrag verwenden
x1 == x2 = 1;
x1 == x3 = 1;
In Rot liefern TRY und CONTAINS die schnellsten Zeiten für bestehende und neue Einträge. In Grün könnte DEFAULT 0 ein guter Kompromiss sein. Es hängt wirklich davon ab, wie viele Einträge erstellt und wie oft sie nachgeschlagen werden.