2013-07-27 127 views
3

我正在處理包含字符串數組的字典列表。這些字典是通過循環在DataTable上定義/填充的。在下面的代碼中,測試評估爲false(兩次),有人可以告訴我爲什麼?字符串數組查找字典

List<Dictionary<string[], int>> mydix = new List<Dictionary<string[], int>>(); 

mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 

string[] s = {"tree"}; 
mydix[1].Add(s, 1); 
bool test = mydix[1].ContainsKey(s); // This evaluates to true, which I understand 
var entry= mydix[1][s]; // This is 1 

DataTable dt=new DataTable(); 
dt.Columns.Add("test"); 
dt.Rows.Add(new string[] {"key"});    
mydix[2].Add(dt.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 2); 
test = mydix[2].ContainsKey(new string[] { "key" }); // Why does this evaluate to false? 

// Here is an example with an array with two elements 
DataTable dt2 = new DataTable(); 
dt2.Columns.Add("test"); 
dt2.Columns.Add("test2");  
string[] t={"tree1","tree2"}; 
dt2.Rows.Add(t); 
mydix[0].Add(dt2.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 3); 
test = mydix[0].ContainsKey(t); // Why does this evaluate to false? 
+0

[This](http://stackoverflow.com/questions/670063/getting-hash-of-a-list-of-strings) 幫助我將散列函數概括爲字符串 – user2546346

回答

1

的問題是,字符串數組您使用爲重點,以字典做對象比較,而不是內容比較。

爲了支持這種類型的數據作爲關鍵,最簡單的解決方案是使用IEqualityComparer

首先,建立比較器(這是一個樣本,你將需要額外的健全檢查和邏輯):

private class ArrayComparer : IEqualityComparer<string[]> 
    { 
     public bool Equals(string[] item1, string[] item2) 
     { 
      if (item1[0] == item2[0]) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 


     public int GetHashCode(string[] item) 
     { 
      return item[0].GetHashCode(); 
     } 

然後,改變你的字典的實例來使用這個新的比較器:

mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 

完成此操作後,兩個測試都會返回true。

+0

謝謝!這確實解決了我的問題。對於C#我還是個新手,正如你所看到的,我對於引用的對象有些困惑。我現在正在努力將這個推廣到具有多於一個元素的字符串數組: DataTable dt2 = new DataTable(); dt2.Columns.Add(「test」); dt2.Columns.Add(「test2」); string [] t = {「tree1」,「tree2」}; dt2.Rows.Add(t); mydix [0] .Add(dt2.Rows [0] .ItemArray.Select(x => x.ToString())。ToArray(),3); test = mydix [0] .ContainsKey(t); //爲什麼這會評估爲false? – user2546346

+0

我在這個評論中的代碼是不可讀的。我在原始文章中包含了泛化(請參見最後一個示例)。你能幫助我嗎? 我可以很容易地擴展公共布爾等於檢查數組的每個元素,但我如何將GetHasCode擴展到項[2]? – user2546346

1

希望有人會糾正我,如果我錯了,但它是我的理解是,當你調用ContainsKey,該Dictionary有一個私有方法(探索dotPeek),它運行到決定將來你的對象比較是否相等。

根據您使用的鍵類型,根據IEqualityComparer的各種實施方式,將會發生不同的相等比較,這樣可根據您希望比較的類型運行最合適的比較。

你正在使用字符串數組作爲鍵,所以你基本上檢查數組對象本身的相等性,而不是它們的內容。所以,你的ContainsKey返回false是完全正確的,你不問你的Dictionary它是否包含相同的數組作爲一個鍵,你問它是否包含不同的數組,恰好包含相同的內容。

IEqualityComparerGetHashCodeGetHashCode方法在這種情況下(一個數組),將返回一個哈希基於對象的引用,而不是內容。

如果你想這種行爲,魔法飛碟雙向先生在這個崗位書面定製IEqualityComparer<T>數組:

Compare Objects?

相關問題