C# Lambda 表达式,如何在对象内部进行搜索?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/415866/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:34:04  来源:igfitidea点击:

Lambda expressions, how to search inside an object?

c#lambda

提问by balexandre

I'm starting to love Lambda expressions but I'm struggling to pass this wall:

我开始喜欢 Lambda 表达式,但我正在努力通过这堵墙:

public class CompanyWithEmployees {
    public CompanyWithEmployees() { }
    public Company CompanyInfo { get; set; }
    public List<Person> Employees { get; set; }
}

My search:

我的搜索:

List<CompanyWithEmployees> companiesWithEmployees = ws.GetCompaniesWithEmployees();
CompanyWithEmployees ces = companiesWithEmployees
        .Find(x => x.Employees
        .Find(y => y.PersonID == person.PersonID));

So, I want to get the Object "CompanyWithEmployees" that have that Person (Employee) that I'm looking for, but I'm getting "Cannot implicit convert 'Person' To 'bool')" which is correct, but if I'm not passing the Person object, how can the first Find executes?

所以,我想得到具有我正在寻找的那个人(雇员)的对象“CompanyWithEmployees”,但我得到“无法隐式转换‘人’到‘布尔’)”这是正确的,但如果我'没有传递 Person 对象,第一个 Find 怎么能执行?

采纳答案by Marc Gravell

Because you want to check for existance, perhaps try:

因为您想检查是否存在,请尝试:

ces = companiesWithEmployees
        .Find(x => x.Employees
        .Find(y => y.ParID == person.ParID) != null);

This will check for any Personwith the same ParID; if you mean the same Personinstance (reference), then Containsshould suffice:

这将检查任何Person具有相同的ParID; 如果您的意思是相同的Person实例(参考),那么Contains应该足够了:

ces = companiesWithEmployees
        .Find(x => x.Employees.Contains(person));

回答by Mehrdad Afshari

ces = companiesWithEmployees
    .First(x => x.Employees.Any(p=>p.PersonID == person.PersonID));

回答by Jon Limjap

That's because you haven't specified a legitimate Find expression for your top level Find.

那是因为您没有为顶级 Find 指定合法的 Find 表达式。

I'll show it here:

我会在这里展示它:

ces = companiesWithEmployees
    .Find (x => x.Employees.Find(y => y.ParID == Person.ParID) /*condition is missing here*/);

So what is the condition for your initial find?

那么你最初发现的条件是什么?

回答by David Schmitt

Find()returns the found object. Use Any()to just check whether the expression is true for any element.

Find()返回找到的对象。使用Any()刚刚检查表达式是否为任何元素如此。

var ces = companiesWithEmployees
    .Find(x => x.Employees
    .Any(y => y.PersonID == person.PersonID));

回答by Michael Buen

ces = companiesWithEmployees.Find( x => x.Employees.Find(...) );

.Findreturns only oneobject, x.Employees.Find(..)returns Person.

.Find返回一个对象,x.Employees.Find(..)返回Person.

.Findexpects boolean parameter(i.e. the result of conditions), that's why there's a compiler error that says Cannot implicit convert 'Person' To 'bool'

.Find期望布尔参数(即条件的结果),这就是为什么有一个编译器错误说 Cannot implicit convert 'Person' To 'bool'

.Wherecan return multiple objects, hence can iterate through alllist.

.Where可以返回多个对象,因此可以遍历所有列表。

use a combination of .Whereand .Anyin your case.

使用的组合.Where.Any你的情况。

the following code will illustrate the difference between .Where, .Find, and .Any:

下面的代码将说明的差之间.Where.Find.Any

public partial class Form2 : Form {
    public Form2() {
        InitializeComponent();
        var companiesWithEmployees = new List<CompanyWithEmployees>() {                
            new CompanyWithEmployees {                 
                CompanyInfo = new Company { CompanyName = "Buen" },
                Employees = new List<Person>()  { 
                    new Person { PersonID = 1976, PersonName = "Michael" },
                    new Person { PersonID = 1982, PersonName = "Mark" },
                    new Person { PersonID = 1985, PersonName = "Matthew" },                            
                    new Person { PersonID = 1988, PersonName = "Morris" }
                }
            },
            new CompanyWithEmployees {
                CompanyInfo = new Company { CompanyName = "Muhlach" },
                Employees = new List<Person>() {
                    new Person { PersonID = 1969, PersonName = "Aga" },
                    new Person { PersonID = 1971, PersonName = "Nino" },
                    new Person { PersonID = 1996, PersonName = "Mark" }
                }
            },
            new CompanyWithEmployees {
                CompanyInfo = new Company { CompanyName = "Eigenmann" },
                Employees = new List<Person>() {
                    new Person { PersonID = 1956, PersonName = "Michael" },                        
                    new Person { PersonID = 1999, PersonName = "Gabby" }
                }
            }
        };

        // just explicitly declared the types (instead of var) so the intent is more obvious

        IEnumerable<CompanyWithEmployees> whereAreMichaels = companiesWithEmployees
            .Where(cx => cx.Employees.Any(px => px.PersonName == "Michael"));

        string michaelsCompanies = string.Join(", ", whereAreMichaels
            .Select(cx => cx.CompanyInfo.CompanyName).ToArray());

        MessageBox.Show("Company(s) with employee Michael : " + michaelsCompanies);

        Person findAga = companiesWithEmployees
            .Find(company => company.CompanyInfo.CompanyName == "Muhlach")
            .Employees.Find(person => person.PersonName == "Aga");

        if (findAga != null)
            MessageBox.Show("Aga's ID : " + findAga.PersonID.ToString());
    }
}

class CompanyWithEmployees { 
    public Company CompanyInfo { get; set; }
    public List<Person> Employees { get; set; }
}
class Company {
    public string CompanyName { get; set; }
}
class Person {
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}

回答by Dincer Uyav

The easiest one would be

最简单的一个是

ces = companiesWithEmployees.FirstOrDefault(x => 
          x.Employees.Any(y => y.PersonID == person.ParID));

without any null check

没有任何空检查