2009-01-06 20 views
7

estoy empezando a amar expresiones lambda, pero estoy luchando para aprobar esta pared:Expresiones lambda, ¿cómo buscar dentro de un objeto?

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

Mi búsqueda:

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

Por lo tanto, quiero conseguir el objeto "CompanyWithEmployees" que tienen esa Persona (Empleado) que estoy buscando, pero estoy obteniendo "No se puede convertir implícitamente 'Persona' a 'bool')" que es correcto, pero si no paso el objeto Persona, ¿cómo puede primero Find ejecuta?

Respuesta

12

Porque desea comprobar si hay existencia, tal vez probar:

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

Esto comprobará para cualquier Person con el mismo ParID; si se refiere a la misma Person instancia (de referencia), Contains debería ser suficiente:

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

La propiedad era 'parid 'cuando publiqué ;-p –

+0

Sí, fue porque tuve que cambiarlo porque es un nombre interno, así que cambié a un pub nombre lic :) Lo siento por eso, pero entiendo el punto :) – balexandre

+0

Debo notar que al usar 'Find', conservas la habilidad de usar 2.0 si lo necesitas; 'Any',' First', etc. requieren 3.5, lo cual es genial si lo tiene ;-p –

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

algo así como David :) llegaste tarde, no voto para ti ;-) pero gracias de todos modos por tu amabilidad y ayuda. – balexandre

+0

En realidad, fui más rápido que David, puedes verificarlo clasificando primero el resultado por el más viejo;) –

0

Eso es porque no se ha especificado un Encuentra expresión legítima de su principio Buscar nivel.

voy a mostrar aquí:

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

Entonces, ¿cuál es la condición para su hallazgo inicial?

7

Find() devuelve el objeto encontrado. Use Any() para verificar si la expresión es verdadera para cualquier elemento.

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

.Find rendimientos sólo una objeto, x.Employees.Find(..) devuelve Person.

.Find espera parámetro booleano (es decir. El resultado de condiciones), es por eso que hay un error de compilación que dice Cannot implicit convert 'Person' To 'bool'

.Where puede devolver varios objetos, por lo tanto, puede recorrer toda lista.

utilice una combinación de .Where y .Any en su caso.

el siguiente código ilustrará la diferencia entre .Where, .Find y .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; } 
} 
0

El más fácil sería

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

sin ninguna verificación nula