[英]What is the most efficient way to do look-up table in C#
在C#中查找表的最有效方法是什么?
我有一張查詢表。 有點像
0 "Thing 1"
1 "Thing 2"
2 "Reserved"
3 "Reserved"
4 "Reserved"
5 "Not a Thing"
因此,如果有人想要“Thing 1”或“Thing 2”,他們會傳遞0或1.但是他們也可以傳遞其他內容。 我有256種這類東西,其中200種是保留的。
那么最有效的想法是什么呢?
我對此解決方案的一個問題是所有“保留”值。 我不想創建那些冗余的“保留”值。 或者我可以對所有“保留”的所有地方都有一個if語句,但它們現在可能只有2-3,可能是2-3,40-55以及字節中的所有不同位置。 這個if語句會變得非常快速
我想知道這是否比創建一個字符串數組或字典更多的處理,只是返回適當的值。
“通過使用其鍵來檢索值非常快,接近於O(1),因為Dictionary(TKey,TValue)類被實現為哈希表。”
var things = new Dictionary<int, string>();
things[0]="Thing 1";
things[1]="Thing 2";
things[4711]="Carmen Sandiego";
在C#中查找整數值的絕對最快方法是使用數組。 如果您嘗試一次進行數萬次查找,這可能比使用字典更可取。 在大多數情況下,這是過度的; 您更有可能需要優化開發人員時間而不是處理器時間。
如果保留鍵不僅僅是查找表中沒有的所有鍵(即,如果查找鍵可以返回找到的值,未找到狀態或保留狀態),則需要保存保留鍵在某處。 將它們保存為具有魔術值的字典條目(例如,保留值為null的任何字典條目的鍵)是正常的,除非您編寫的代碼迭代字典的條目而不過濾它們。
解決該問題的一種方法是使用單獨的HashSet<int>
來存儲保留的鍵,並且可以將整個事物烘焙到類中,例如:
public class LookupTable
{
public readonly Dictionary<int, string> Table { get; }
public readonly HashSet<int> ReservedKeys { get; }
public LookupTable()
{
Table = new Dictionary<int, string>();
ReservedKeys = new HashSet<int>();
}
public string Lookup(int key)
{
return (ReservedKeys.Contains(key))
? null
: Table[key];
}
}
你會注意到這仍然存在魔術值問題 - 如果密鑰是保留的, Lookup
返回null,如果它不在表中,則拋出異常 - 但至少現在你可以迭代Table.Values
而不過濾魔術值。
如果你有很多保留(當前未使用)的值或者整數值的范圍可以變得很大,那么我會使用通用字典(Dictionary):
var myDictionary = new Dictionary<int, string>();
myDictionary.Add(0, "Value 1");
myDictionary.Add(200, "Another value");
// and so on
否則,如果你有一個固定數量的值,並且只有少數當前未被使用,那么我將使用一個字符串數組(字符串[200])並將保留的條目設置/保留為空。
var myArray = new string[200];
myArray[0] = "Value 1";
myArray[2] = "Another value";
//myArray[1] is null
查看HybridDictionary。 它會根據大小自動調整其底層存儲機制,以獲得最大效率。
http://msdn.microsoft.com/en-us/library/system.collections.specialized.hybriddictionary.aspx
內置的Dictionary對象(最好是通用字典)對此是理想的,並且專門設計用於快速/有效地檢索與鍵相關的值。
從鏈接的MSDN文章:
通過使用其鍵來檢索值非常快,接近於O(1),因為Dictionary <(Of <(TKey,TValue>)>)類被實現為哈希表。
就你的“保留”鍵而言,如果我們只討論幾百個鍵/值,我根本不會擔心。 只有當你達到數十,甚至數十萬個“保留”鍵/值時,你才能實現更有效的效果。
在這些情況下,可能最有效的存儲容器可能是稀疏矩陣的實現。
我不太確定我是否理解你的問題。 你有一組字符串。 每個字符串都與索引相關聯。 除非保留索引,否則使用者請求會提供索引並返回相應的字符串。 對?
你不能簡單地在數組中將保留項設置為null。
如果沒有,使用不包含保留項的字典似乎是一個合理的解決方案。
無論如何,如果你澄清你的問題,你可能會得到更好的答案。
將所有值加載到
var dic = new Dictionary<int, string>();
並使用它來檢索:
string GetDescription(int val)
{
if(0 <= val && val < 256)
if(!dic.Contains(val))
return "Reserved";
return dic[val];
throw new ApplicationException("Value must be between 0 and 255");
}
我會使用Dictionary來進行查找。 到目前為止,這是最有效的查找方式。 使用字符串將在O(n)區域中的某處運行以查找對象。
如果需要,可以讓第二個字典對所有人進行反向查找
您的問題似乎暗示查詢鍵是一個整數。 由於您最多有256個項目,因此查詢鍵的范圍為0..255,對嗎? 如果是這樣,只需要一個256字符串的字符串數組,並使用該鍵作為數組的索引。
如果您的查詢鍵是字符串值,那么它更像是一個真正的查找表。 使用Dictionary對象很簡單,但是如果你的原始速度只有50個左右的實際答案,那么自己動手的方法,比如二元搜索或trie,可能會更快。 如果您使用二進制搜索,由於項目數量太少,您可以將其展開。
項目列表多久更改一次? 如果它只是很少變化,你可以通過生成代碼進行搜索來獲得更好的速度,然后你可以編譯並執行每個查詢。
另一方面,我假設你已經證明這個查找是你的瓶頸,無論是通過分析還是采用stackshots 。 如果在此查詢中花費的時間少於10%,那么它不是您的瓶頸,因此您可以做最容易編碼的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.