2012-05-17 5 views
18

주위를 둘러 보았고 여기서 도움이 될만한 것을 찾을 수 없습니다. 나는 교차와 Linq는 방법을 제외하고 사용하고자하는C# Linq는 오브젝트의 한 부분을 제외하고는 교차합니다.

class ThisClass 
{ 
    private string a {get; set;} 
    private string b {get; set;} 
} 

, 즉 :

private List<ThisClass> foo = new List<ThisClass>(); 
private List<ThisClass> bar = new List<ThisClass>(); 

가 그럼 난 별도로 두 목록을 채우기 : 나는 클래스를 가지고있다.
foo[a].Intersect(bar[a]); 

어떻게 이런 짓을 했을까

다음, 나는 예를 들어, 할 싶습니다 (나는이 그냥 의사하지 못했습니다 알고)? 어떤 도움

감사합니다 :)

+0

넌 뭐니? 이 줄'foo [a] .Intersect (bar [a]); '에서 원하는 것을 단어로 설명하십시오. –

답변

25

아마

// returns list of intersecting property 'a' values 
foo.Select(f => f.a).Intersect(bar.Select(b => b.a)); 

은 BTW 재산 a 공개해야한다.

+0

니스, 간단한, 내가 필요한 것. 당신과 모든 응답자들 덕분입니다. –

2
foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a)) 
16

교차하려는 단일 속성의 목록을 원하면 다른 모든 멋진 LINQ 솔루션이 올바르게 작동합니다. 하지만! 그래도 전체 클래스와 교차하고 싶다면 List<string> 대신 List<ThisClass>이 있어야합니다. 자신 만의 평등 비교자를 작성해야합니다.

foo.Intersect(bar, new YourEqualityComparer()); 

Except과 동일합니다.

public class YourEqualityComparer: IEqualityComparer<ThisClass> 
{ 

    #region IEqualityComparer<ThisClass> Members 


    public bool Equals(ThisClass x, ThisClass y) 
    { 
     //no null check here, you might want to do that, or correct that to compare just one part of your object 
     return x.a == y.a && x.b == y.b; 
    } 


    public int GetHashCode(ThisClass obj) 
    { 
     unchecked 
     { 
      var hash = 17; 
          //same here, if you only want to get a hashcode on a, remove the line with b 
      hash = hash * 23 + obj.a.GetHashCode(); 
      hash = hash * 23 + obj.b.GetHashCode(); 

      return hash;  
     } 
    } 

    #endregion 
} 
-2

IEqualityComparer를 만들어야합니다. IEqualityComparer를 Intersect() 메서드에 전달할 수 있습니다. 이렇게하면 List (bar와 교차)를 쉽게 얻을 수 있습니다.

var intersectionList = foo.Intersect(bar, new ThisClassEqualityComparer()).ToList(); 


class ThisClassEqualityComparer : IEqualityComparer<ThisClass> 
{ 

    public bool Equals(ThisClass b1, ThisClass b2) 
    { 
     return b1.a == b2.a; 
    } 


    public int GetHashCode(Box bx) 
    { 
     // To ignore to compare hashcode, please consider this. 
     // I would like to force Equals() to be called 
     return 0; 
    } 

} 
+1

이렇게 해시 코드에서 '0'을 반환하면 안됩니다. 성능이 완전히 저하 될 것입니다. 대신 해시 코드 'a'를 사용해야합니다. – Servy

0

정확히 원하는 효과는 무엇입니까? 두 개의 ThisClass 인스턴스가 고유 한 값인 a으로 식별되면 클래스에있는 a으로 구성된 문자열 목록 또는 ThisClass의 목록을 가져 오시겠습니까?

전자 메일 인 경우 @lazyberezovksy 및 @Tilak의 두 답변이 작동해야합니다. 다음

private class ThisClass : IEquatable<ThisClass> 
{ 
    private string a; 

    public bool Equals(ThisClass other) 
    { 
     return string.Equals(this.a, other.a); 
    } 
} 

방금 ​​호출 할 수 있습니다 :

var intersection = foo.Intersect(bar);  
+1

'IEquatable'을 구현할 때 항상'GetHashCode'를 오버라이드해야합니다. 당신이하지 않기 때문에, 이것은 작동하지 않습니다. – Servy

3

의 확실하지가 후자의 경우 IntersectThisClass 상당의 두 인스턴스를 만드는 것 알 수 있도록, 당신은 IEqualityComparer<ThisClass> 또는 IEquatable<ThisClass>를 재정의해야합니다 이 속도는 교차와 비교하는 비교하지만 대한 방법 :

//Intersect 
var inter = foo.Where(f => bar.Any(b => b.a == f.a)); 
//Except - values of foo not in bar 
var except = foo.Where(f => !bar.Any(b => b.a == f.a)); 
+3

이것은 O (n * m) 알고리즘이고'Intersect'와'Except'는 모두'O (n + m)'입니다. 그게 너를 훨씬 더 악화시킨다. 'bar '를 여러 번 반복하면 모든 상황에서 주요한 문제가 될 수 있습니다 (각 반복마다 동일한 결과를 얻지 못할 수도 있고, 데이터베이스를 쿼리하거나 각 반복마다 비싼 계산을 수행 할 수도 있습니다. 부작용이있을 수 있습니다. 반복 할 때 발생합니다. – Servy

0

내가 아는이 오래지만 수없는 당신 클래스 자체에서 Equals & GetHashCode를 재정의하면됩니까?

class ThisClass 
{ 
    public string a {get; set;} 
    private string b {get; set;} 

    public override bool Equals(object obj) 
    { 
    // If you only want to compare on a 
    ThisClass that = (ThisClass)obj; 
    return string.Equals(a, that.a/* optional: not case sensitive? */); 
    } 

    public override int GetHashCode() 
    { 
    return a.GetHashCode(); 
    } 
}