2013-07-27 95 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?

相关问题