简体   繁体   English

根据参数过滤对象列表

[英]Filter a list of objects based on a parameter

class Officer
{
    Person person;
}

class Person
{
    string name;
} 

Suppose I've a list of Officer and a list of Person. 假设我有一个官员名单和一个人名单。 I want to filter these two list based on some criteria. 我想根据某些条件过滤这两个列表。

So I wrote this method: 所以我写了这个方法:

public List<Person> filterName(List<Person> list)
{
   // some filter logic
}

And I'm using this method for the two lists in the following way: 我通过以下方式针对两个列表使用此方法:

main()
{
     ...
     List<Officer> officers = Initialize();
     List<Person> validNames= filterNames(officers.Select(o=>o.person.name).ToList())
     foreach (var officer in officers)
     {
          if (!validNames.Contains(officer.Person.name))
                 officers.remove(officer);
     }
     // finally I have a valid set of officers here

     List<Person> persons = Initialize();
     var filteredPersons = filterNames(persons.Select(o=>o.name).ToList())
}

Is there a good way to use generics so I can avoid the following code in the main method()? 是否有使用泛型的好方法,所以我可以避免在main method()中使用以下代码?

 List<string> validNames = filterNames(officers.Select(o=>o.fullName).ToList())
 foreach (var officer in officers)
 {
      if (!validNames.Contains(officer.name))
             officers.remove(officer);
 }

And use generics somehow to update the officers list using generics. 并以某种方式使用泛型来使用泛型更新人员列表。

New answer based on recent edits: 根据最近编辑的新答案:

var officers = new List<Officer>
{
    new Officer { Name = "Officer Foo" },
    new Officer { Name = "Officer Bar" }
};

officers.RemoveAll(o => o.Name.Contains("Bar"));
// Officers now only contains "Officer Foo"

------------ Old answer here ---------------- ------------ 这里的旧答案 ----------------

Can you use OOP here and derive Person and Officer from something in common? 您可以在此处使用OOP并从某个共同点派生PersonOfficer吗?

If so, then you can easily take their common property and filter on that instead of writing two separate pieces of logic to deal with each of them. 如果是这样,那么您可以轻松地采用它们的公共属性并对其进行过滤,而不用编写两个单独的逻辑来处理它们中的每一个。

static void Main(string[] args)
{
    var officers = new List<Officer>
    {
        new Officer { Name = "Officer Foo" },
        new Officer { Name = "Officer Bar" }
    };

    var workers = new List<Worker>
    {
        new Worker { Name = "Worker Foo" },
        new Worker { Name = "Worker Bar" }
    };

    var people = workers.Cast<IPerson>().Concat(officers);
    var filteredPeople = Program.Filter(people, "Foo");

    Console.ReadKey(true);
}

static IEnumerable<IPerson> Filter(IEnumerable<IPerson> people, string keyword)
{
    return people.Where(p => p.Name.Contains(keyword));
}

interface IPerson
{
    string Name { get; set; }
}

class Officer : IPerson
{
    public string Name { get; set; }
}

class Worker : IPerson
{
    public string Name { get; set; }
}

Ok, let's assume you have some complicated FilterNames function that operates on a list, and your goal is to filter out based on some Person criteria. 好的,假设您有一些复杂的FilterNames函数对列表进行操作,并且您的目标是根据某些Person条件进行过滤。 I would rewrite the filter like this: 我会这样重写过滤器:

public bool FilterPerson(Person p)
{
    //Some complicated logic
    //Returns true if person should be kept
    //Returns false if the person should be rejected
}

Now you can use that in a Linq statement: 现在,您可以在Linq语句中使用它:

var officers = Initialize().Where(o => FilterPerson(o.Person)).ToList();

No need to remove items from the list. 无需从列表中删除项目。 You could still use the interim object, it just requires an additional step: 您仍然可以使用临时对象,只需执行一个附加步骤:

var officers = Initialize();    //Returns List<Officer>
var filteredOfficers = officers.Where(o => FilterPerson(o.Person)).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM