2009-10-14 14 views
121

Tengo una List<BuildingStatus> llamados buildingStatus. Me gustaría comprobar si contiene un estado cuyo código de char (devuelto por GetCharCode()) es igual a alguna variable, v.Status.LINQ: "contiene" y una consulta Lambda

¿Hay alguna manera de hacer esto, a lo largo de las líneas de código (no compilación) por debajo?

buildingStatus.Contains(item => item.GetCharValue() == v.Status) 

Respuesta

232

Uso Any() en lugar de Contains():

buildingStatus.Any(item => item.GetCharValue() == v.Status) 
+6

Agradable. Me sigo preguntando por qué en Earth Linq no proporciona un método 'Contains()', y luego me doy cuenta de que se supone que es 'Any()' en su lugar. +1 – Nolonar

30

El método de LINQ extensión Cualquier podría funcionar para usted ...

buildingStatus.Any(item => item.GetCharValue() == v.Status) 
3

No estoy seguro exactamente lo que' está buscando, pero este programa:

public class Building 
    { 
     public enum StatusType 
     { 
      open, 
      closed, 
      weird, 
     }; 

     public string Name { get; set; } 
     public StatusType Status { get; set; } 
    } 

    public static List <Building> buildingList = new List<Building>() 
    { 
     new Building() { Name = "one", Status = Building.StatusType.open }, 
     new Building() { Name = "two", Status = Building.StatusType.closed }, 
     new Building() { Name = "three", Status = Building.StatusType.weird }, 

     new Building() { Name = "four", Status = Building.StatusType.open }, 
     new Building() { Name = "five", Status = Building.StatusType.closed }, 
     new Building() { Name = "six", Status = Building.StatusType.weird }, 
    }; 

    static void Main (string [] args) 
    { 
     var statusList = new List<Building.StatusType>() { Building.StatusType.open, Building.StatusType.closed }; 

     var q = from building in buildingList 
       where statusList.Contains (building.Status) 
       select building; 

     foreach (var b in q) 
      Console.WriteLine ("{0}: {1}", b.Name, b.Status); 
    } 

produce la salida esperada:

one: open 
two: closed 
four: open 
five: closed 

Este programa compara una representación de cadena de la enumeración y produce la misma salida:

public class Building 
    { 
     public enum StatusType 
     { 
      open, 
      closed, 
      weird, 
     }; 

     public string Name { get; set; } 
     public string Status { get; set; } 
    } 

    public static List <Building> buildingList = new List<Building>() 
    { 
     new Building() { Name = "one", Status = "open" }, 
     new Building() { Name = "two", Status = "closed" }, 
     new Building() { Name = "three", Status = "weird" }, 

     new Building() { Name = "four", Status = "open" }, 
     new Building() { Name = "five", Status = "closed" }, 
     new Building() { Name = "six", Status = "weird" }, 
    }; 

    static void Main (string [] args) 
    { 
     var statusList = new List<Building.StatusType>() { Building.StatusType.open, Building.StatusType.closed }; 
     var statusStringList = statusList.ConvertAll <string> (st => st.ToString()); 

     var q = from building in buildingList 
       where statusStringList.Contains (building.Status) 
       select building; 

     foreach (var b in q) 
      Console.WriteLine ("{0}: {1}", b.Name, b.Status); 

     Console.ReadKey(); 
    } 

he creado este método de extensión de convertir un IEnumerable en otro, pero no estoy seguro de lo eficiente que es; puede simplemente crear una lista detrás de escena.

public static IEnumerable <TResult> ConvertEach (IEnumerable <TSource> sources, Func <TSource,TResult> convert) 
{ 
    foreach (TSource source in sources) 
     yield return convert (source); 
} 

A continuación, puede cambiar la cláusula dónde:

where statusList.ConvertEach <string> (status => status.GetCharValue()). 
    Contains (v.Status) 

y omitir la creación de la List<string> con ConvertAll() al principio.

+0

Gracias a Larry que funcionó, esto es lo que hice al referirme a su código ... Pero sería bueno si fuera posible si no tuviera que crear una nueva lista ??? // Utilicé ToList porque es un ILIST y ejecuto mi GetCharValue // esto produce una "NUEVA" lista con mi char var statusStringList = building.ToList(). ConvertAll (st => st.GetCharValue()); var test = from v en qry donde statusStringList.Contains (v.Status) select v; Todo funciona, como digo sería bueno no tener que hacer una nueva lista o usar una lambda dentro de Contiene pero parece que NO es posible? –

+0

Supongo que la propiedad de estado es una cadena; por lo tanto, debe convertir las enumeraciones de estado en cadenas para cada comparación. También podría convertirlos una vez al principio y terminar con eso. – XXXXX

+0

He realizado una edición que simplifica significativamente la pregunta pero, al hacerlo, invalida esta respuesta. Perdón por eso, pero pensé que era para un bien general. –

-1

Si entiendo correctamente, debe convertir el tipo (valor de char) que almacena en la lista de Construcción al tipo (enumeración) que almacena en la lista buildingStatus.

(Para cada estado en la lista de construcción // // valor de carácter, hace existe el estado en la lista buildingStatus // // valor de enumeración)

public static IQueryable<Building> WithStatus(this IQueryable<Building> qry, 
     IList<BuildingStatuses> buildingStatus) 
    { 
     return from v in qry 
       where ContainsStatus(v.Status) 
       select v;   
    } 


private bool ContainsStatus(v.Status) 
{ 
foreach(Enum value in Enum.GetValues(typeof(buildingStatus))) 
{ 
    If v.Status == value.GetCharValue(); 
    return true; 
} 
return false; 
} 
+0

-1; aunque mi edición de la pregunta ha invalidado ligeramente esta respuesta eliminando toda referencia a 'Building' de la pregunta, esto ya * estaba realmente roto *. 'foreach (valor de Enum en Enum.GetValues ​​(typeof (buildingStatus)))' no tiene sentido. –

0

Aquí es cómo se puede utilizar para Contains lograr lo que quiere:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) esto devolverá un valor booleano.