2013-07-27 3 views
3

문자열 배열이 포함 된 사전 목록을 가지고 작업하고 있습니다. 사전은 DataTable 이상의 루프를 통해 정의/채워집니다. 다음 코드 테스트에서 false (2 회)로 평가됩니다. 누군가 왜 저에게 말할 수 있습니까?문자열 배열 검색 사전

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

이 주석의 코드는 실제로 읽을 수 없습니다.원래 게시물에 일반화를 포함 시켰습니다 (마지막 예 참조). 그걸 도와 줄 수있어? public boolean Equals를 쉽게 확장하여 배열의 모든 요소를 ​​검사 할 수 있지만 GetHasCode를 항목 [2]로 확장하는 방법은 무엇입니까? – user2546346

1

다행스럽게도 필자가 틀렸다면 누군가가 나가 해결됩니다, 그러나 당신이 ContainsKey를 호출 할 때 Dictionary 당신이있어 개체 어떠했는지를 결정하기 위해 실행되는 개인 방법 (dotPeek 탐험)을 가지고 나의 이해입니다 비교는 동일하거나 또는 동일하지 않습니다.

키에 사용하는 유형에 따라 IEqualityComparer의 다양한 구현에 따라 서로 다른 평등 비교가 수행되므로 비교하려는 유형에 따라 가장 적절한 비교를 실행할 수 있습니다.

문자열 배열을 키로 사용하므로 본질적으로 내용이 아닌 배열 객체 자체의 동일성을 검사하게됩니다. 따라서 ContainsKey이 false를 반환한다는 것이 완전히 맞습니다. Dictionary에 키와 동일한 배열이 포함되어 있는지 묻지 않으면 동일한 배열을 포함하는 다른 배열이 있는지 묻는 것입니다.

IEqualityComparerGetHashCode 메서드는이 경우 (배열) 메서드는 내용이 아닌 개체 참조를 기반으로 해시를 반환합니다. 이 동작을 원하는 경우, 마법 씨 스키트이 게시물에 배열에 대한 사용자 지정 IEqualityComparer<T>를 작성했습니다

:

Compare Objects?