Toujours en train de jouer avec les tendances Twitter. J'ai suffisamment de données collectées pour que j'aimerais accélérer le traitement. Je souhaite attribuer un index entier à chaque mot de tendance en utilisant un tableau associatif indexé avec le mot de tendance. Vous trouverez ci-dessous trois techniques pour ajouter un nouveau mot au tableau ou obtenir l'index d'un ancien mot.
Le premier utilise TRY pour intercepter l'exception lorsqu'un mot n'est pas dans la table. C'est le plus rapide si le mot est présent et le plus lent (de loin) si l'exception se produit.
La seconde utilise CONTAINS pour tester si le mot est présent, puis l'ajoute ou le recherche. C'est le plus rapide pour l'ajout et le plus lent pour la recherche (car il recherche deux fois.)
Le dernier utilise une valeur par défaut de tableau associatif pour voir si la valeur récupérée existe déjà. Il offre un bon compromis vitesse.
Tous les exemples ont une boucle "t" qui s'exécute deux fois. La première fois, le tableau xN est vide et doit être rempli. La deuxième fois, toutes les valeurs seront déjà présentes.
// 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 );
Essayez la méthode : 2,851 secondes pour créer une nouvelle entrée
Essayez la méthode : 0,099 secondes utiliser l'entrée existante
Contient la méthode : 0,209 secondes créer une nouvelle entrée
Contient la méthode : 0,151 seconde utilise l'entrée existante
méthode 0 par défaut : 0,259 secondes créer une nouvelle entrée
méthode 0 par défaut : 0,117 secondes utiliser l'entrée existante
x1 == x2 = 1 ;
x1 == x3 = 1 ;
En rouge, TRY et CONTAINS fournissent les temps les plus rapides pour les entrées existantes et nouvelles. En vert, DEFAULT 0 pourrait être un bon compromis. Cela dépend vraiment du nombre d'entrées qui seront créées et du nombre de fois qu'elles seront recherchées.
Merci pour le rappel! J'ai choisi une valeur par défaut en dehors de l'ensemble des valeurs autorisées pour mon exemple, donc pas vraiment utile par défaut. Zéro est un index invalide pour ma recherche. J'ai commencé avec missing, mais isMissing(x) est plus cher que x==0.
Travaille actuellement sur des trucs d'API REST et à cause de cela Tableaux associatifs et suppression des clés avec la même valeur que la valeur par défaut J'ai/j'éviterai d'utiliser les valeurs par défaut. La raison étant que j'utilise la réponse JSON pour créer une interface utilisateur interactive pour les utilisateurs JMP et j'ai besoin des clés même si elles ont une "valeur par défaut". Mais je pense que je vais arrêter d'utiliser l'option paresseuse d'utiliser Essayez de vérifier les clés manquantes après ce post.
Voir plus...