Ich spiele immer noch mit Twitter-Trends. Ich habe genügend 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. Im Folgenden finden Sie drei Techniken zum Hinzufügen eines neuen Worts zur Tabelle oder zum Abrufen des Index für ein altes Wort.
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 (bei weitem) am langsamsten, wenn die Ausnahme auftritt.
Der zweite verwendet CONTAINS, um zu testen, ob das Wort vorhanden ist, und fügt es dann hinzu oder sucht nach. Es ist am schnellsten beim Hinzufügen und am langsamsten beim Nachschlagen (da zweimal nachgeschlagen wird).
Letzteres verwendet einen assoziativen Array-Standardwert, um festzustellen, 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 );
Methode ausprobieren: 2,851 Sekunden neuen Eintrag erstellen
Versuchen Sie es mit der Methode: 0,099 Sekunden verwenden vorhandenen Eintrag
Enthält Methode: 0,209 Sekunden neuen Eintrag erstellen
Enthält Methode: 0,151 Sekunden vorhandenen Eintrag verwenden
Standardmethode 0: 0,259 Sekunden neuen Eintrag erstellen
Standardmethode 0: 0,117 Sekunden verwenden vorhandenen Eintrag
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 werden und wie oft sie nachgeschlagen werden.
Danke für die Erinnerung! Ich habe für mein Beispiel einen Standardwert gewählt, der außerhalb der zulässigen Werte liegt und daher als Standard nicht wirklich nützlich ist. Null ist ein ungültiger Index für meine Suche. Ich habe mit Missing angefangen, aber isMissing(x) ist teurer als x==0.
Derzeit arbeite ich an einigen REST-API-Sachen und aus diesem Grund Assoziative Arrays und Entfernung von Schlüsseln mit dem gleichen Wert wie dem Standardwert Ich habe bzw. werde es vermeiden, Standardwerte zu verwenden. Der Grund dafür ist, dass ich JSON-Antworten verwende, um eine interaktive Benutzeroberfläche für JMP-Benutzer zu erstellen, und dass ich die Schlüssel auch dann benötige, wenn sie einen „Standardwert“ haben. Aber ich denke, ich werde nach diesem Beitrag aufhören, die Lazy-Option zu verwenden und nach fehlenden Schlüsseln zu suchen.
Mehr sehen...