まだツイッターのトレンドで遊んでいます。 処理を高速化するのに十分なデータが収集されています。 トレンドワードでインデックス付けされた連想配列を使用して、各トレンドワードに整数インデックスを割り当てたいと思います。 以下に、テーブルに新しい単語を追加したり、古い単語のインデックスを取得したりするための3つの手法があります。
1つ目は、単語がテーブルにない場合にTRYを使用して例外をキャッチします。 単語が存在する場合は最速で、例外が発生した場合は(はるかに)遅くなります。
2つ目は、CONTAINSを使用して単語が存在するかどうかをテストし、それを追加または検索します。 追加するのが最も速く、検索するのが最も遅い(2回検索するため)。
最後は、連想配列のデフォルト値を使用して、取得した値がすでに存在するかどうかを確認します。 それは素晴らしい妥協速度を提供します。
すべての例には、2回実行される「t」ループがあります。 初めてxN配列が空になり、入力する必要があります。 2回目は、すべての値がすでに存在します。
// 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 );
方法を試す:2.851秒で新しいエントリを作成
方法を試してください: 0.099秒は既存のエントリを使用します
メソッドが含まれています: 0.209秒は新しいエントリを作成します
メソッドが含まれています:0.151秒は既存のエントリを使用します
デフォルトの0メソッド: 0.259秒は新しいエントリを作成します
デフォルトの0メソッド: 0.117秒は既存のエントリを使用します
x1 == x2 = 1;
x1 == x3 = 1;
赤字のTRYとCONTAINSは、既存のエントリと新しいエントリに最速の時間を提供します。 緑の場合、DEFAULT0が適切な妥協案である可能性があります。 これは、実際には、作成されるエントリの数と、それらが検索される回数によって異なります。