2012-02-10 7 views
0

フィルタ式に基づいて2つのリストを比較したいと思います。ジェネリックメソッドのラムダ式をどのように構築するかわからない。下記のコードを参照してください。またはLINQの交差を介してより簡単な方法がありますか?式/ lambdaを使用して2つのリストを比較/フィルタする一般的な方法

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

Aha !!例外エクステンションはまさに私が必要なものです!ありがとうございました:-)はい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; 
     } 
    } 


} 
関連する問題