Лямбда-выражения, как искать внутри объекта?

StackOverflow https://stackoverflow.com/questions/415866

  •  03-07-2019
  •  | 
  •  

Вопрос

Я начинаю любить лямбда-выражения, но изо всех сил пытаюсь пройти эту стену:

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 " у меня есть тот Персона (Сотрудник), которого я ищу, но я получаю " Невозможно неявно преобразовать «Персона» в «bool») " что правильно, но если я не передаю объект Person, как может выполняться первый Find?

Это было полезно?

Решение

Поскольку вы хотите проверить наличие, попробуйте:

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

Это проверит для любого Персона с тем же ParID ; Если вы имеете в виду один и тот же экземпляр Person (ссылка), тогда достаточно Contains :

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

Другие советы

Find () возвращает найденный объект. Используйте Any () , чтобы просто проверить, является ли выражение истинным для любого элемента.

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

.Find возвращает только один объект, x.Employees.Find (..) возвращает Person .

.Find ожидает логический параметр (то есть результат условий), поэтому есть ошибка компилятора, которая говорит, что не может неявно преобразовать «Person» в «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; }
}

Это потому, что вы не указали правильное выражение Find для своего верхнего уровня Find.

Я покажу это здесь:

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

Итак, каково условие для вашей начальной находки?

Самый простой будет

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

без проверки на ноль

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top