仍在玩推特趨勢。 我收集了足夠的數據,希望加快處理速度。 我想通過使用以趨勢詞索引的關聯數組為每個趨勢詞分配一個整數索引。 下面提供了三種向表中添加新單詞或獲取舊單詞索引的技術。
第一個使用 TRY 來捕獲單詞不在表中時的異常。 如果單詞存在,它是最快的;如果發生異常,它是最慢的(到目前為止)。
第二個使用 CONTAINS 來測試該單詞是否存在,然後添加它或查找它。 它的添加速度最快,查找速度最慢(因為它查找兩次。)
最後一個使用關聯數組默認值來查看檢索到的值是否已存在。 它提供了一個很好的折衷速度。
所有示例都有一個運行兩次的“t”循環。 第一次 xN 數組為空,必須填充。 第二次時,所有值都已存在。
// 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 提供現有條目和新條目的最快時間。 在綠色中,DEFAULT 0 可能是一個很好的折衷方案。 這實際上取決於將創建多少條目以及將查找它們多少次。
感謝您的提醒! 我在示例中選擇了允許值集之外的默認值,因此作為默認值並沒有多大用處。 零對於我的查找來說是無效的索引。 我從 Missing 開始,但是 isMissing(x) 比 x==0 更昂貴。
目前正在研究一些 REST API 的東西,因此關聯數組和刪除與默認值相同的鍵我已經/將避免使用默認值。 原因是我使用 JSON 響應為 JMP 用戶構建交互式 UI,即使它們具有“默認值”,我也需要這些鍵。 但我想在這篇文章之後我將停止使用嘗試檢查丟失的密鑰的惰性選項。
查看更多...