gpt4 book ai didi

c# - 按集合过滤 IEnumerable (Linq)

转载 作者:行者123 更新时间:2023-11-30 14:30:05 25 4
gpt4 key购买 nike

我想通过它正在收集的任何对象的特定属性来过滤 IEnumerable 对象。我想要按一个或多个属性值过滤的选项但是要过滤多少个值(以及哪些值)仅在运行时才知道。

好吧,举个例子,收集的对象可以是以下结构:

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"};

然后把这个放到一个IEnumerable中(先全部传给它)

var wantedPeople = from n in this.people select n;

假设用户只对“裁缝”和“ spy ”职业感兴趣,并且通过某种 gui 技巧创建了以下集合:

List<string> wantedProfessions = new List<string>();
wantedProfessions.Add("Tailor");
wantedProfessions.Add("Spy");

现在,我可以使用什么 Linq 语句来归档我的 wantedPeople,以便它只包含 tailor 和 spy 条目?我知道我可以使用 where 子句,但我不知道如何调整它以获得我想要的(并且执行以下操作不是我想要的,因为它只适用于上面的 wantedProfessions 集合(例如,此集合将在运行时更改):

wantedPeople = from n in wantedPeople
where n.Profession == wantedProffessions[0] || n.Profession == wantedProffessions[1]
select n;

最佳答案

如果你想从给定的列表中检查任何想要的职业:

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));

如果你想创建更复杂的过滤器,比如一些名字和几个职业,你可以使用 Specification pattern .规范可以通过这个简单的接口(interface)来定义:

public interface ISpecification<T>
{
bool Satisfied(T entity);
}

它只是检查给定的实体(人)是否满足规范。规范看起来也很简单:

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);
}
}

您可以创建实现 bool 逻辑的规范,例如 OrSpecification 或 AndSpecification:

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);

关于c# - 按集合过滤 IEnumerable (Linq),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24336334/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com