67 votos

LINQ: "contiene" y una consulta de Lambda

Tengo una lista que contiene las enumeraciones, es un estándar de la Enumeración, pero tiene un atributo que se le atribuye y un método de extensión que devuelve un carácter de la enumeración (ver más abajo - GetCharValue), la extensión de las grandes obras.

Ahora tengo (otro método de extensión para linq)

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

Yo, básicamente, hay que decir "Devolver" todo en pregunta, pero sólo si v. Estado es en buildingStatus... pero recuerde buildingStatus es una ILIST de enumeraciones así que me DEBE llamar a GetCharValue.

Tuve un poco de ayuda previamente había yo creo que la sintaxis correcta es

buildingStatus.Contains (v.Status)   

pero el problema aquí es que buildingStatus es un Ilist de Enumeraciones así que debo llamar GetCharValue() en cada Elemento de la interfaz Ilist antes de decir Contiene..

Yo estaba pensando que había algo especial forma de hacer esto con lambda mediante Contiene como así - por supuesto que no funciona

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

Alguien puede ayudar?

140voto

Rex M Puntos 80372

Uso Any() en vez de contiene:

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

24voto

flq Puntos 11937

El método de extensión de Linq cualquier podría trabajar para usted...

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

5voto

XXXXX Puntos 667

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 el resultado esperado:

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


Este programa compara una cadena con la representación de la enumeración y produce el mismo resultado:

    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 para convertir un IEnumerable a otro, pero no estoy seguro de cuán eficiente es; sólo se puede crear una lista de detrás de las escenas.

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 where:

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

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

0voto

psabela Puntos 71

Si no me equivoco, necesitas convertir al tipo (char valor) que almacena en lista de edificio para el tipo (enum) que almacena en la lista de buildingStatus.

(Para cada estado en la lista de edificio / / valor de caracteres / /, existe el estado en la lista de buildingStatus / / valor enum / /)

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;
}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X