C# 按集合筛选IEnumerable(Linq)
我想根据IEnumerable对象收集的任何对象的特定属性来过滤它。我希望选项按一个或多个属性值进行筛选,但只有在运行时才知道要按多少值(以及哪些值)进行筛选 好,举个例子,收集的对象可以是以下结构:C# 按集合筛选IEnumerable(Linq),c#,linq,C#,Linq,我想根据IEnumerable对象收集的任何对象的特定属性来过滤它。我希望选项按一个或多个属性值进行筛选,但只有在运行时才知道要按多少值(以及哪些值)进行筛选 好,举个例子,收集的对象可以是以下结构: public struct Person { public string Name { get; set; } public string Profession{ get; set; } } 然后,以下列表可以使用此结构,我已经用一些任意值填充了该列表: List<Pers
public struct Person
{
public string Name { get; set; }
public string Profession{ get; set; }
}
然后,以下列表可以使用此结构,我已经用一些任意值填充了该列表:
List<Person> people= new List<Person>;
people.Add(new Person(){Name = "Mickey", Profession="Tinker"};
people.Add(new Person(){Name = "Donald", Profession="Tailor"};
people.Add(new Person(){Name = "Goofy", Profession="Soldier"};
people.Add(new Person(){Name = "Pluto", Profession="Spy"};
假设用户只对“裁缝”和“间谍”职业感兴趣,通过某种gui欺骗,创建了以下集合:
List<string> wantedProfessions = new List<string>();
wantedProfessions.Add("Tailor");
wantedProfessions.Add("Spy");
如果您想从给定列表中检查任何想要的职业:
wantedPeople = from n in wantedPeople
where wantedProffessions.Contains(n.Profession)
select n;
或者,您可以通过逐个应用过滤器,使用lambda语法构建查询:
var query = people.AsEnumerable();
if (!String.IsNullOrEmpty(name))
query = query.Where(p => p.Name == name);
if (wantedProfessions.Any())
query = query.Where(p => wantedProfessions.Contains(p.Profession));
如果您想创建更复杂的过滤器,比如一些名字和一些职业,您可以使用。可通过以下简单接口定义规范:
public interface ISpecification<T>
{
bool Satisfied(T entity);
}
并获得所需人员:
var result = people.Where(spec.Satisfied);
Sergey B的解决方案对于您的示例来说是正确的 假设您没有使用包含Contains()方法的集合,也可以执行以下操作:
var wantedPeople = from n in people
from p in wantedProffessions
where n.Profession.Equals(p)
select n;
实际上,在这种情况下,我会使用
join
——它在内部创建查找,这比枚举两个集合O(n*m)更有效,感谢Sergey和Apologies的长时间延迟。
public class PersonNameSpecification : ISpecification<Person>
{
private string _name;
public PersonNameSpecification(string name)
{
_name = name;
}
public bool Satisfied(Person person)
{
return person.Name == _name;
}
}
public class PersonProfessionSpecification : ISpecification<Person>
{
private string[] _professions;
public PersonProfessionSpecification(params string[] professions)
{
_professions = professions;
}
public bool Satisfied(Person person)
{
return _professions.Contains(person.Profession);
}
}
public class AndSpecification<T> : ISpecification<T>
{
private ISpecification<T> _specA;
private ISpecification<T> _specB;
public AndSpecification(ISpecification<T> specA, ISpecification<T> specB)
{
_specA = specA;
_specB = specB;
}
public bool Satisfied(T entity)
{
return _specA.Satisfied(entity) && _specB.Satisfied(entity);
}
}
public static class SpecificationExtensions
{
public static ISpecification<T> And<T>(
this ISpecification<T> specA, ISpecification<T> specB)
{
return new AndSpecification<T>(specA, specB);
}
}
var professionSpec = new PersonProfessionSpecification("Tailor", "Spy");
var nameSpec = new PersonNameSpecification("Pluto");
var spec = professionSpec.And(nameSpec);
var result = people.Where(spec.Satisfied);
var wantedPeople = from n in people
from p in wantedProffessions
where n.Profession.Equals(p)
select n;