2012-02-10 2 views
0

필터 식을 기반으로 두 목록을 비교하려고합니다. 일반 메서드에 대해 람다 식을 구성하는 방법을 모릅니다. 아래 코드를 참조하십시오. 또는 LINQ에서 교차를 통해 더 쉬운 방법이 있습니까?식/lambda를 사용하여 두 목록을 비교/필터링하는 일반적인 방법

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Data d1 = new Data {Id = 1, Name = "One"}; 
      Data d2 = new Data { Id = 2, Name = "Two" }; 
      Data d3 = new Data { Id = 3, Name = "Three" }; 

      Data d4 = new Data { Id = 1, Name = "One" }; 
      Data d5 = new Data { Id = 2, Name = "Two" }; 
      Data d6 = new Data { Id = 4, Name = "Four" }; 

      List<Data> original = new List<Data> {d1, d2, d3}; 
      List<Data> filterItems = new List<Data> {d4, d5, d6}; 

      List<Data> result = original.FilterDataList(filterItems); 

      //How to call this method? 
      List<Data> genericCall = original.FilterList<Data>(filterItems, data => data.Id ?????????????) 
     } 
    } 

    public class Data 
    { 
     public long Id; 
     public string Name; 
    } 

    public static class Extensions 
    { 
     public static List<Data> FilterDataList(this List<Data> sourceList, List<Data> filterOutItems) 
     { 
      return sourceList.Where(p => filterOutItems.All(l => l.Id != p.Id)).ToList(); 
     } 

     public static List<T> FilterList<T>(this List<T> sourceList, List<T> filterOutItems, Func<T, bool> filterExpression) 
     { 
      return sourceList.Where(p => filterOutItems.All(filterExpression)).ToList(); 
     } 
    } 
} 

답변

1

질문을 올바르게 이해하면 FilterList은 매개 변수로 람다를 전달하는 FilterDataList의 제네릭 버전입니다.

List<Data> genericCall = original.FilterList<Data>(filterItems, (x, y) => x.Id != y.Id); 

당신이 @ivancho 및 @perelman를 제외하고 사용하려는 경우는이 같은 방법을 사용할 수 있습니다 제안 :

public static class EnumerableExtension 
{ 
    public static IEnumerable<T> Except<T>(this IEnumerable<T> listA, IEnumerable<T> listB, 
              Func<T, T, bool> lambda) 
    { 
     return listA.Except(listB, new Comparer<T>(lambda)); 
    } 

    public static IEnumerable<T> Intersect<T>(this IEnumerable<T> listA, IEnumerable<T> listB, 
               Func<T, T, bool> lambda) 
    { 
     return listA.Intersect(listB, new Comparer<T>(lambda)); 
    } 
} 

을 당신은 다음하고자 다음과 같이이 경우 당신은 메소드를 호출 할 것이다 다음과 같이 전화 : 모든 사람에게

original.Except<Data>(filterItems, (x, y) => x.Id != y.Id); 
+0

아하 !! Except 확장 기능은 내가 필요로하는 것입니다! 그것 주셔서 감사합니다 :-) 예 FilterList는 (x, y) => x.Id! = y.Id는 Func 으로 작업하지 않습니다. –

1

원하는 출력은 무엇입니까? https://www.google.com/search?q=linq+intersect의 첫 번째 결과를 시도 했습니까? Enumerable 문서를 살펴보아야 할 것 같습니다. 가장 가능성이 높은 곳에서 .All을 사용하고 있습니다. 일반적으로 LINQ를 통해 가능한 것이 무엇인지 더 잘 이해할 수 있습니다.

1

나는 무엇을 하려는지 명확하지 않습니다. FilterDataListExcept().ToList()과 같습니다. FilterList에있는 .Wherep (람다에 대한 인수)을 사용하지 않으므로 필터 식으로 무엇을하고 싶은지 확실하지 않습니다. 다른 클래스로 정의해야 할 Except()과 다른 IEqualityComparer을 사용하려고합니다.

1

감사를 확장 밖으로 제외하고 LINQ를 가리키는 위해, 여기 내 엔드 솔루션입니다

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Data d1 = new Data {Id = 1, Name = "One"}; 
      Data d2 = new Data { Id = 2, Name = "Two" }; 
      Data d3 = new Data { Id = 3, Name = "Three" }; 

      Data d4 = new Data { Id = 1, Name = "One" }; 
      Data d5 = new Data { Id = 2, Name = "Two" }; 


      List<Data> original = new List<Data> {d1, d2, d3}; 
      List<Data> filterItems = new List<Data> {d4, d5, d6}; 


      List<Data> datas = original.Except(filterItems, (x, y) => x.Id == y.Id).ToList(); 
     } 
    } 

    public class Data 
    { 
     public long Id; 
     public string Name; 
    } 

    public static class EnumerableExtension 
    { 
     public static IEnumerable<T> Except<T>(this IEnumerable<T> listA, IEnumerable<T> listB, 
               Func<T, T, bool> lambda) 
     { 
      return listA.Except(listB, new Comparer<T>(lambda)); 
     } 

     public static IEnumerable<T> Intersect<T>(this IEnumerable<T> listA, IEnumerable<T> listB, 
                Func<T, T, bool> lambda) 
     { 
      return listA.Intersect(listB, new Comparer<T>(lambda)); 
     } 
    } 


    public class Comparer<T> : IEqualityComparer<T> 
    { 
     private readonly Func<T, T, bool> _expression; 

     public Comparer(Func<T, T, bool> lambda) 
     { 
      _expression = lambda; 
     } 

     public bool Equals(T x, T y) 
     { 
      return _expression(x, y); 
     } 

     public int GetHashCode(T obj) 
     { 
      /* 
      If you just return 0 for the hash the Equals comparer will kick in. 
      The underlying evaluation checks the hash and then short circuits the evaluation if it is false. 
      Otherwise, it checks the Equals. If you force the hash to be true (by assuming 0 for both objects), 
      you will always fall through to the Equals check which is what we are always going for. 
      */ 
      return 0; 
     } 
    } 


} 
관련 문제