簡體   English   中英

將C#詞典與“黃金標准”詞典進行相等性比較的最快方法是什么?

[英]What is the quickest way to compare a C# Dictionary to a 'gold standard' Dictionary for equality?

我有一個已知良好的字典,在運行時,我需要創建一個新的Dictionary並運行檢查以查看它是否具有與已知良好字典相同的鍵值對(可能以不同的順序插入),並采用如果可行,一條路徑,如果不可行,另一條路徑。 我不一定需要序列化整個已知有效字典(例如,我可以使用哈希),但是我需要一些磁盤數據,其中包含有關已知良好字典的足夠信息,以便進行比較(如果沒有)娛樂。 最快的方法是什么? 我可以使用SortedDictionary,但是初始化和添加值所需的時間長短取決於此任務的速度。

具體示例:

考慮一個字典<String,List<String>>看起來像這樣(顯然沒有特定的順序):

{ {"key1", {"value1", "value2"} }, {"key2", {"value3", "value4"} } }  

我創建了一次Dictionary,並將有關它的某種形式的信息保存在磁盤上(完整的序列化,哈希,等等)。 然后,在運行時,執行以下操作:

Dictionary<String,List<String>> d1 = new Dictionary<String,List<String>> ();
Dictionary<String,List<String>> d2 = new Dictionary<String,List<String>> ();
Dictionary<String,List<String>> d3 = new Dictionary<String,List<String>> ();

String key11 = "key1";
String key12 = "key1";
String key13 = "key1";
String key21 = "key2";
String key22 = "key2";
String key23 = "key2";

List<String> value11 = new List<String> {"value1", "value2"};
List<String> value12 = new List<String> {"value1", "value2"};
List<String> value13 = new List<String> {"value1", "value2"};
List<String> value21 = new List<String> {"value3", "value4"};
List<String> value22 = new List<String> {"value3", "value4"};
List<String> value23 = new List<String> {"value3", "value5"};

dict1.add(key11, value11);
dict1.add(key21, value21);
dict2.add(key22, value22);
dict2.add(key12, value12);
dict3.add(key13, value13);
dict3.add(key23, value23);

dict1.compare(fileName); //Should return true
dict2.compare(fileName); //Should return true
dict3.compare(fileName); //Should return false

同樣,如果從啟動到compare()返回的整體時間更快,我可以更改此代碼以使用SortedDictionary(或其他任何方法),但是我不能保證排序,我需要一些一致的比較。 compare()可以加載序列化並在字典中進行迭代,可以序列化內存中的字典並將序列化與文件名進行比較,或者可以執行許多其他操作。

解決方案一:使用集合相等。

如果字典的大小不同,您會知道它們是不相等的。

如果它們的大小相同,則從一個字典構建一個可變的散列鍵集。 從中刪除其他詞典中的所有鍵。 如果您嘗試刪除一個不存在的密鑰,則密鑰集不相等,並且您知道問題出在哪個密鑰上。

另外,構建兩個哈希集並取它們的交集; 所得交集應為原始集合的大小。

這需要O(n)時間和O(n)空間。

一旦知道鍵集相等,就一次遍歷所有鍵,獲取值,然后進行值比較。 由於這些值是序列,因此請使用SequenceEquals。 這需要O(n)時間和O(1)空間。

解決方案二:按鍵排序

同樣,如果字典的大小不同,您會知道它們是不相等的。

如果它們的大小相同,則對兩組密鑰進行排序,並對它們進行SequenceEquals; 如果鍵序列不相等,則字典不相等。

這需要O(n lg n)時間和O(n)空間。

如果成功,則再次一次通過一個鍵並比較這些值。

解決方法三:

再次,檢查字典以查看它們的大小是否相同。

如果它們是,則遍歷一個詞典的鍵並檢查該鍵是否存在於另一詞典中。 如果不是,則它們不相等。 如果是這樣,則檢查相應的值是否相等。

時間為O(n),空間為O(1)。

如何在這些可能的解決方案中進行選擇? 這取決於可能的故障模式,以及是否需要知道丟失或多余的密鑰是什么。 如果可能的故障模式是一個壞鍵,那么選擇一個解決方案的性能可能更高,該解決方案首先要查找壞鍵,並且如果所有鍵都確定為OK,則僅檢查壞值。 如果可能的故障模式是一個錯誤的值,則第三個解決方案可能是最好的,因為它會優先考慮檢查值的優先級。

由於我對接受的答案有任何評論,因此我們進行了更嚴格的檢查。

goodDictionary.Keys.All(k=>
    {
        List<string> otherVal;
        if(!testDictionary.TryGetValue(k,out otherVal))
        {
            return false;
        }
        return goodDictionary[k].SequenceEquals(otherVal);
    })

如果您已經進行了序列化,則獲取每個序列化字典的哈希值(我建議使用SHA-1),然后進行比較。

我認為這里沒有神奇的子彈。 您只需要為每個密鑰對進行查找:

public bool IsDictionaryAMatch(Dictionary<string, List<string>> dictionaryToCheck)
{
    foreach(var kvp in dictionaryToCheck)
    {
         // Do the Keys Match
         if(!goodDictionary.Exists(x => x.Key == kvp.Key))
             return false;

         foreach(var valueElement in kvp.Value)
         {
              // Do the Values in each list match
              if(!goodDictionary[kvp.Key].Exists(x => x == valueElement))
                  return false;
         }
    }

    return true;
}

好吧,在某些時候,您需要比較每個鍵具有相同的值,但是在此之前,您可以做一些快速的事情,例如檢查每個字典有多少個鍵,然后檢查鍵列表是否匹配。 這些測試應該相當快,如果其中任何一個測試失敗,您可以中止更昂貴的測試。

之后,您可能能夠構建單獨的鍵列表,然后觸發Paraells查詢以比較實際值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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