1

今日、dear 述語によってさらに単純化された非常に単純な問題に直面しました。一種のイベント ログがあり、条件のリストを使用してクライアント側 (Windows フォーム) でフィルター処理したいと考えていました。いくつかのカテゴリでフィルタリングする実装から始めました。

private List<Events> FilterEventsByCategory(List<Events> events,
                                        List<Category> categories) 
{
  return events.FindAll(ev => 
      categories.Exists(category => category.CategoryId==ev.CategoryId)); 
}

次のステップは、他のいくつかのフィルターを実装することです。これらを一般化して、フィルターごとに 1 つのメソッドを作成する必要がないようにする良い方法を知っていますか? または、少なくとも、同時に適用したいフィルターの動的リストを作成するクリーンな方法です。

クライアントはまだフレームワーク 3.0 を使用しているため、LINQ はありません。

更新: 自分のソリューションの功績を認めるべき人物を決めるのに苦労しました。マークにはいくつかの素晴らしいアイデアがあり、それらを説明するのが本当に上手です。私の問題をもう少しうまく説明していれば、おそらく彼から答えが得られたでしょう。最終的に、私を軌道に乗せたのは、cmartin が提供した汎用 Filter クラスでした。以下で使用される Filter クラスは、cmartins の回答と、自分で思いつく User クラスにあります。

var categoryFilter = new Filter<Event>(ev => categories.Exists(category => category.CategoryId == ev.CategoryId));
var userFilter = new Filter<Event>(ev => users.Exists(user => user.UserId == ev.UserId));

var filters = new List<Filter<Event>>();
filters.Add(categoryFilter);
filters.Add(userFilter);

var eventsFilteredByAny = events.FindAll(ev => filters.Any(filter => filter.IsSatisfied(ev)));
var eventsFilteredByAll = events.FindAll(ev => filters.All(filter => filter.IsSatisfied(ev)));
4

2 に答える 2

2

re "so no LINQ" - LINQBridgeを見ましたか? C# 3.0 を使用しているので、これは理想的です...

主な質問で恐縮ですが、あなたが何をしようとしているのか、何を避けようとしているのかを完全には理解していません。はっきりさせていただけますか? ただし、LINQBridge アプローチを使用すると、連続した.Where()呼び出しを使用してフィルターを組み合わせることができます。

質問の解釈の 1 つは、多くのフィルター メソッドは必要ないということです。そのため、1 つ以上の述語をメソッドに渡します。基本的には a として、Func<Event, Func<Category, bool>>または純粋な 2.0 用語では a Converter<Event, Predicate<Category>>:

private static List<Events> FilterEvents(
    List<Events> events,
    List<Category> categories,
    Converter<Events, Predicate<Category>> func)
{
    return events.FindAll(evt =>
        categories.Exists(func(evt)));
}

これは(上記のように)次のように使用されます。

var result = FilterEvents(events, categories,
      evt => category => category.CategoryId==evt.CategoryId);
于 2009-01-29T23:13:27.803 に答える
1

これは、私がどこから始めるかの非常に初歩的なサンプルです。

internal class Program
{
    private static void Main()
    {
        var ms = new Category(1, "Microsoft");
        var sun = new Category(2, "Sun");

        var events = new List<Event>
                         {
                             new Event(ms, "msdn event"),
                             new Event(ms, "mix"),
                             new Event(sun, "java event")
                         };

        var microsoftFilter = new Filter<Event>(e => e.CategoryId == ms.CategoryId);

        var microsoftEvents = FilterEvents(events, microsoftFilter);

        Console.Out.WriteLine(microsoftEvents.Count);
    }

    public static List<Event> FilterEvents(List<Event> events, Filter<Event> filter)
    {
        return events.FindAll(e => filter.IsSatisfied(e));
    }
}

public class Filter<T> where T: class
{
    private readonly Predicate<T> criteria;

    public Filter(Predicate<T> criteria)
    {
        this.criteria = criteria;
    }

    public bool IsSatisfied(T obj)
    {
        return criteria(obj);
    }
}

public class Event
{
    public Event(Category category, string name)
    {
        CategoryId = category.CategoryId;
        Name = name;
    }

    public int CategoryId { get; set; }
    public string Name { get; set; }
}

public class Category
{
    public Category(int categoryId, string name)
    {
        CategoryId = categoryId;
        Name = name;
    }

    public string Name { get; set; }
    public int CategoryId { get; set; }
}
于 2009-01-29T23:25:19.217 に答える