Reputation: 329
I want to write an extension method to filter all the people with towns in a people object with the towns in shop object
class people
string name
string town
class shops
string category
string town
i know i can write
var x = from p in people
from s in shops
where p.town == s.town
but i would like to know how to write
var x = from p in people.FilterByTown(p) or FilterByTown(p => p.town) or however it is!!
where FilterByTown is the extension method and all the magic works in there and the object i pass in gets compared with the shop object.
It needs to work with different objects being fed to the method
Hope that all makes sense, the code above is obviously pseudo!
Upvotes: 1
Views: 264
Reputation: 3348
Assuming you have 2 collections people and shops you can write this:
List<People> people = ...
List<Shops> shops = ...
IEnumerable<People> Filter(this IEnumerable<People> people, IEnumerable<Shops> shops){
var result = people.Where(p=>shops.Any(s=>s.town == p.town));
return result;
}
If you want to sort all classes by some arbitrary property you can try this version:
public static IEnumerable<T1> Filter<T1, T2>(
this IEnumerable<T1> one,
IEnumerable<T2> two, string property)
{
var result = one.Where(o => two.Any(t =>
o.GetType().GetProperty(property).
GetValue(o, null).Equals(t.GetType().
GetProperty(property).GetValue(t, null))));
return result;
}
Of course you need to be sure that property is valid and both objects have it.
Upvotes: 1
Reputation: 14502
Using reflection, you can filter based on any property of any type:
public static IEnumerable<T> FilterByProperty<T>(this IEnumerable<T> source,
string property,
object value)
{
var propertyInfo = typeof(T).GetProperty(property);
return source.Where(p => propertyInfo.GetValue(p, null) == value);
}
Usage:
IEnumerable<People> cityPeople = myPeople.FilterByTown("Town", "MyCity");
And if you want a list:
List<People> cityPeopleList = myPeople.FilterByTown("MyCity").ToList();
Upvotes: 2
Reputation: 112279
You can speed up the queries if you create a list of unique towns
public static class PeopleExtensions
{
private static List<string> _distinctShopTowns;
private static List<Shop> _shops;
public static List<Shop> Shops
{
get { return _shops; }
set {
_shops = value;
_distinctShopTowns = _shops
.Select(shop => shop.town)
.Distinct()
.ToList();
}
}
public static IEnumerable<Person> PeopleInTownsWithShops(this IEnumerable<Person> people)
{
return people.Where(p => _distinctShopTowns.Contains(p.town));
}
}
You can call it like this
List<Shop> shops = ...;
List<Person> people = ...;
PeopleExtensions.Shops = shops; // Do every time the shop list changes.
var x = from p in people.PeopleInTownsWithShops();
Upvotes: 0
Reputation: 1024
If I understand your question correctly you want something like this:
public static IEnumerable<People> FilterByTown(this IEnumerable<People> people, IList<Shop> shops)
{
return people.Where(p => shops.Any(s => s.Town == p.Town));
}
Usage:
peoples.FilterByTown(shops);
Upvotes: 0