그래서 객체 모음이 있습니다. 정확한 유형은 중요하지 않습니다. 그것으로부터 특정 속성 쌍의 모든 고유 쌍을 추출하고 싶습니다.
myObjectCollection.Select(item=>new
{
Alpha = item.propOne,
Bravo = item.propTwo
}
).Distinct();
그래서 내 질문은 :이 경우 기본 객체 같음 (각 객체가 새 것이기 때문에 나에게 쓸모가 없음)을 사용하거나 다른 같음 (이 경우 알파와 브라보의 동일한 값)을 수행하도록 지시받을 수 있습니다 => 동일한 인스턴스)? 그렇지 않은 경우 해당 결과를 달성 할 수있는 방법이 있습니까?
답변
K. Scott Allen의 훌륭한 게시물을 읽으십시오.
짧은 대답 (및 인용) :
익명 유형에 대해 C # 컴파일러가 Equals 및 GetHashCode를 대체합니다. 재정의 된 두 메서드의 구현은 형식의 모든 공용 속성을 사용하여 개체의 해시 코드를 계산하고 동등성을 테스트합니다. 익명 유형이 동일한 두 개체의 속성 값이 모두 같은 경우 개체가 동일합니다.
따라서 익명 형식을 반환하는 쿼리에서 Distinct () 메서드를 사용하는 것이 안전합니다.
답변
public class DelegateComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> _equals;
private Func<T, int> _hashCode;
public DelegateComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
{
_equals= equals;
_hashCode = hashCode;
}
public bool Equals(T x, T y)
{
return _equals(x, y);
}
public int GetHashCode(T obj)
{
if(_hashCode!=null)
return _hashCode(obj);
return obj.GetHashCode();
}
}
public static class Extensions
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
Func<T, T, bool> equals, Func<T,int> hashCode)
{
return items.Distinct(new DelegateComparer<T>(equals, hashCode));
}
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
Func<T, T, bool> equals)
{
return items.Distinct(new DelegateComparer<T>(equals,null));
}
}
var uniqueItems=students.Select(s=> new {FirstName=s.FirstName, LastName=s.LastName})
.Distinct((a,b) => a.FirstName==b.FirstName, c => c.FirstName.GetHashCode()).ToList();
이전에 엉망인 형식으로 죄송합니다.
답변
C #에서는 작동하지만 VB에서는 작동하지 않는다는 흥미로운
26자를 반환합니다 :
var MyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
MyBet.ToCharArray()
.Select(x => new {lower = x.ToString().ToLower(), upper = x.ToString().ToUpper()})
.Distinct()
.Dump();
52를 반환합니다 …
Dim MyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
MyBet.ToCharArray() _
.Select(Function(x) New With {.lower = x.ToString.ToLower(), .upper = x.ToString.ToUpper()}) _
.Distinct() _
.Dump()
답변
약간의 테스트를 실행하여 속성이 값 유형 인 경우 제대로 작동하는 것으로 나타났습니다. 값 유형이 아닌 경우, 유형이 작동하려면 자체 Equals 및 GetHashCode 구현을 제공해야합니다. 문자열은 효과가 있다고 생각합니다.
답변
람다 식을 사용하는 고유 한 고유 확장 방법을 만들 수 있습니다. 여기에 예가 있습니다
IEqualityComparer 인터페이스에서 파생되는 클래스 만들기
public class DelegateComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> _equals;
private Func<T, int> _hashCode;
public DelegateComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
{
_equals= equals;
_hashCode = hashCode;
}
public bool Equals(T x, T y)
{
return _equals(x, y);
}
public int GetHashCode(T obj)
{
if(_hashCode!=null)
return _hashCode(obj);
return obj.GetHashCode();
}
}
그런 다음 Distinct Extension 방법을 작성하십시오.
public static class Extensions
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
Func<T, T, bool> equals, Func<T,int> hashCode)
{
return items.Distinct(new DelegateComparer<T>(equals, hashCode));
}
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
Func<T, T, bool> equals)
{
return items.Distinct(new DelegateComparer<T>(equals,null));
}
}
이 방법을 사용하면 별개의 항목을 찾을 수 있습니다
var uniqueItems=students.Select(s=> new {FirstName=s.FirstName, LastName=s.LastName})
.Distinct((a,b) => a.FirstName==b.FirstName, c => c.FirstName.GetHashCode()).ToList();
답변
경우 Alpha
와 Bravo
일반 클래스에서 모두 상속, 당신은 구현하여 부모 클래스에서 동등 검사를 지시 할 수있을 것입니다 IEquatable<T>
.
예를 들면 다음과 같습니다.
public class CommonClass : IEquatable<CommonClass>
{
// needed for Distinct()
public override int GetHashCode()
{
return base.GetHashCode();
}
public bool Equals(CommonClass other)
{
if (other == null) return false;
return [equality test];
}
}
답변
이봐 거기에 같은 문제가 있고 해결책을 찾았습니다. IEquatable 인터페이스를 구현하거나 단순히 (Equals & GetHashCode) 메서드를 재정의해야합니다. 그러나 이것은 트릭이 아닙니다. 트릭은 GetHashCode 메서드에서 제공됩니다. 클래스 객체의 해시 코드를 반환하지 말고 비교하려는 속성의 해시를 반환해야합니다.
public override bool Equals(object obj)
{
Person p = obj as Person;
if ( obj == null )
return false;
if ( object.ReferenceEquals( p , this ) )
return true;
if ( p.Age == this.Age && p.Name == this.Name && p.IsEgyptian == this.IsEgyptian )
return true;
return false;
//return base.Equals( obj );
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
보시다시피 person이라는 클래스에 3 개의 속성이 있습니다 (Name, Age, IsEgyptian “Breuse I am”) GetHashCode에서 Person 개체가 아닌 Name 속성의 해시를 반환했습니다.
그것을 시도하면 ISA가 작동합니다. 감사합니다, Modather Sadik
