【问题标题】:Lambda expressions, how to search inside an object?Lambda表达式,如何在对象内部搜索?
【发布时间】:2009-01-06 08:59:04
【问题描述】:

我开始喜欢 Lambda 表达式,但我很难通过这堵墙:

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

我的搜索:

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

所以,我想获取对象“CompanyWithEmployees”,该对象具有我正在寻找的那个人(员工),但我得到“无法隐式将'Person'转换为'bool') em>" 是正确的,但是如果我没有传递 Person 对象,第一个 Find 怎么执行?

【问题讨论】:

    标签: c# lambda


    【解决方案1】:

    因为你想检查是否存在,不妨试试:

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

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

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

    【讨论】:

    • 我发帖时属性是ParID ;-p
    • 是的,我不得不更改它,因为它是一个内部名称,所以我更改为一个公共名称 :) 对此我很抱歉,但我明白了 :)
    • 我应该注意,仅使用Find,您可以在需要时保留使用 2.0 的能力; AnyFirst 等需要 3.5 - 如果你有它,那就太好了;-p
    • 我最终使用了 .Contains,谢谢 Marc。 Lambda 表达式不是一种享受吗? :-D
    • 我正在使用 get;放;很多...所以我需要 3.x ;)
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:
      ces = companiesWithEmployees
          .First(x => x.Employees.Any(p=>p.PersonID == person.PersonID));
      

      【讨论】:

      • 有点像大卫 :) 你迟到了,没有人支持你 ;-) 但还是感谢你的好意和帮助。
      • 其实我比大卫还快,你可以通过将结果按最旧的排序来检查它;)
      【解决方案4】:
      ces = companiesWithEmployees.Find( x => x.Employees.Find(...) );
      

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

      .Find 需要布尔参数(即条件的结果),这就是为什么编译器错误提示 Cannot implicit convert 'Person' To 'bool'

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

      在您的情况下使用.Where.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; }
      }
      

      【讨论】:

        【解决方案5】:

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

        我会在这里展示:

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

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

        【讨论】:

          【解决方案6】:

          最简单的应该是

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

          没有任何空检查

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-27
            • 2010-12-10
            • 2013-07-02
            • 2018-11-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多