bflemi3
bflemi3

Reputation: 6790

How to enumerate through list of Func<TSource,TResult> to filter collection

I'm trying, unsuccessfully, to enumerate through a List<Func<InstagramUser,bool>> to filter a collection of List<InstagramUser>. My code compiles, but just returns the whole list, unfiltered, when display() is invoked.

My question is, what is the proper way to hold a collection of lambda expressions that can then be used to filter another collection?

public class InstagramDisplay {
    public IList<InstagramUser> instagramUsers;
    public IList<Func<InstagramUser, bool>> instagramFilters; 

    public InstagramDisplay() {
        instagramUsers = new List<InstagramUser>();
        instagramFilters = new List<Func<InstagramUser, bool>>();
    }

    public void addFilter(Func<InstagramUser, bool> filter, object filterValue) {
        if ((int)(filterValue ?? 0) > 0)
            instagramFilters.Add(filter);
    }

    public IEnumerable<InstagramUser> display() { //filter not working
        instagramFilters.ToList().ForEach(filter => instagramUsers.Where(filter));
        return instagramUsers;
    }
}

Invocation - just returns full collection, unfiltered:

InstagramDisplay instagramDisplay = new InstagramDisplay();
instagramDisplay.instagramUsers = (List<InstagramUser>)context.Cache[CACHE_KEY];
instagramDisplay.addFilter(u => u.id == instagramId, instagramId);
context.Response.Write(javascriptSerializer.Serialize(instagramDisplay.display());

Upvotes: 2

Views: 492

Answers (2)

Marcelo De Zen
Marcelo De Zen

Reputation: 9497

If you want to include users that matches all the filters (an AND comparison):

instagramUsers.Where(u => instagramFilters.All(f => f(u)));

If you want to include users that matches 1 or more filters, change the All by Any in the statement above.

Upvotes: 6

Reed Copsey
Reed Copsey

Reputation: 564433

The problem is that your ForEach statement doesn't actually use or store the results of the Where method you are running. You need to build a resulting IEnumerable<T>, and filter it in series.

You could write this as:

public IEnumerable<InstagramUser> display() { 
    IEnumerable<InstagramUser> users = instagramUsers;
    foreach(var filter in instagramFilters)
        users = users.Where(filter);
    return users;
}

Upvotes: 2

Related Questions