簡體   English   中英

在C#中查找表的最有效方法是什么?

[英]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語句會變得非常快速

  • 我想的另一個選擇是switch語句。 而且我將獲得所有50個已知值並且將通過默認值保留值。

我想知道這是否比創建一個字符串數組或字典更多的處理,只是返回適當的值。

  • 別的什么? 還有另一種方法可以考慮嗎?

“通過使用其鍵來檢索值非常快,接近於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM