2011-12-19 2 views
1

먼저 다음과 비교할 내용을 말씀 드리겠습니다. 내 사용자 지정 개체 (항목)에 문자열 목록 taxids이 있습니다. .두 개의 사용자 지정 개체 비교 (IEqualityComparer 사용)

public class Item 
{ 
    public long taxid { get; set; } 
    public long contentid { get; set; } 
    public string taxname { get; set; } 
    public IEnumerable<string> taxids { get; set; } 
} 

그런 다음이 : 나는 한 목록에있는 모든 문자열이 문자열의 다른 목록에 발생하는 경우 (또 다른 객체 (품목)의 또 다른 taxids 것보고 싶지 그래서

, 이것은 클래스 더미 사용자 정의 객체는 다음과 같습니다

여기
List<string> numbers = new List<string> { "5", "1" }; 
    List<string> numbers2 = new List<string> { "1", "2", "5","3","564" }; 

    Item pr = new Item(); 
    pr.contentid = 2517; 
    pr.taxid = 2246; 
    pr.taxids = numbers.AsEnumerable(); 
    pr.taxname = "nameItem1"; 
    List<Item> te = new List<Item>(); 
    te.Add(pr); 
    IQueryable<Item> er = te.AsQueryable(); 

    Item pr2 = new Item(); 
    pr2.contentid = 0; 
    pr2.taxid = 0; 
    pr2.taxids = numbers2.AsEnumerable(); 
    pr2.taxname = "nameItem2"; 
    List<Item> te2 = new List<Item>(); 
    te2.Add(pr2); 
    IQueryable<Item> er2 = te2.AsQueryable(); 

    IQueryable<Item> both = er.Intersect(er2, new ItemComparer()); 

내가 사용자 지정 비교 자 ItemComparer를 사용 다음은이에 대한 코드입니다.

public class ItemComparer : IEqualityComparer<Item> 
{ 
    // items are equal if their names and item numbers are equal. 
    public bool Equals(Item x, Item y) 
    { 
     //Check whether the compared objects reference the same data. 
     if (Object.ReferenceEquals(x, y)) return true; 

     //Check whether any of the compared objects is null. 
     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 

     //Check whether the items' properties are equal. 
     return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids); 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 
    public int GetHashCode(Item item) 
    { 
     //Check whether the object is null 
     if (Object.ReferenceEquals(item, null)) return 0; 

     //Get hash code for the Name field if it is not null. 
     int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode(); 

     //Calculate the hash code for the item. 
     return item.taxids.GetHashCode(); 

     //return "a".GetHashCode(); 
    } 
} 

문제는 변수 both은 택시 필드에 아무 것도 가지고 있지 않습니다. 일반적으로 "5" "1"의 목록이 있어야합니다.

비교할 때 hashCode가 같아야한다는 것을 알고 있습니다. 그러나 taxids은 결코 동일하지 않습니다. 다른 문자열 목록에서 문자열을 찾기 때문입니다.

아무도이 문제에 대해 도움을 줄 수 있습니까? 또한

(작은 질문

: 나는 "a".GetHashCode() =>해야이 작업 여부 등 모든 것을 항상 같은 해시 코드를 반환하는 경우

사전에 감사

답변

2

나는 귀하의 문제는 양방향 평등이 없다고 생각합니다. 당신의 대상이 어느 쪽인지에 따라, pr과 pr 2는 같지 않습니다.

나는 개체가 x이고 y가 귀하의 비교 자에 대한 보증이 있는지 확실하지 않습니다. 비교 자에서 pr2의 숫자가 x 인 경우 어떻게됩니까?

해시 코드에 관해서는 taxids.GetHashCode()입니다. 이것은 단지 목록이며 이름이 아니며 평등에 관해 알려주지 않습니다.

0
return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids); 

귀하의 평등 비교가 현재 고려하지 않습니다 컬렉션의 요소 순서가 다를 수 있습니다. 일반적인 해결 방법으로 비교하기 전에 순서를 지정하거나 해시 집합에 항목을 더하는 것이 좋습니다.

return x.taxids.Intersect(y.taxids) 
       .OrderBy(x => x) 
       .SequenceEqual(x.taxids.OrderBy(x => x)); 

또한 GetHashCode()의 적절한 구현을 제공해야하며 기본 구현은 목록의 실제 항목에 종속되지 않으므로 컬렉션에 같은 요소가있는 두 개의 서로 다른 Item 인스턴스에 대해 동일한 해시 코드가 생성되지는 않습니다. 귀하의 사례에 대한보다 적절한 구현은 this other SO post에서 찾을 수 있습니다.

+0

instersect를 수행 할 때 항상 동일한 순서로 반환됩니다. 하지만 정보를 주셔서 감사합니다 – Ozkan

+0

컬렉션 중 하나에서 요소가 수집 된 순서대로 반환됩니다 (그리고 의존하지 않아도됩니다). 이것은 다른 컬렉션의 항목과 반드시 ​​같을 필요가 없으므로 다시 정렬해야합니다. – BrokenGlass

+0

정보를 제공해 주셔서 감사합니다. 그리고 getHashcode 메소드. 어쩌면 당신은 저보다 더 많이 압니다. 모든 것에 항상 동일한 해시 코드를 사용할 수 있습니까? 예를 들면 다음과 같습니다 :' "a".GetHashCode()'.왜냐하면 나는 결코 똑같은 두 가지 목록을 가지지 않을 것이기 때문입니다. 당신이 준 URL에서 뚜렷하게하는 것으로 목록을 동일하게 만들 수는 있지만 목록에는 완전히 다른 항목이 있습니다. – Ozkan