LINQ: "contiene" y una consulta Lambda


168

He una List<BuildingStatus>llamada buildingStatus. Me gustaría comprobar si contiene un estado cuya carbón código (que devuelve GetCharCode()) es igual a alguna variable, v.Status.

¿Hay alguna forma de hacerlo, en la línea del código (sin compilación) a continuación?

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

Respuestas:


320

Usar en Any()lugar de Contains():

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

13
Agradable. Me sigo preguntando por qué en la Tierra Linq no proporciona un Contains()método, y luego me doy cuenta de que se supone que es así Any(). +1
Nolonar

38

El método de extensión Linq Cualquiera podría funcionar para usted ...

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

4

Así es como puede usar Containspara lograr lo que desea:

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


3

No estoy seguro de lo que estás 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 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 ();
    }

Creé este método de extensión para convertir un IEnumerable a otro, pero no estoy seguro de cuán eficiente 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);
}

Luego puede cambiar la cláusula where a:

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

y omita crear el List<string>con ConvertAll ()al principio.


Gracias 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. // Usé ToList porque es una ILIST y ejecuté mi GetCharValue // esto produce una lista "NUEVA" con el estado var de mi charStringList = building.ToList (). ConvertAll <char> (st => st.GetCharValue ()); prueba var = desde v en qry donde statusStringList.Contains (v.Status) selecciona 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.
mark smith

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ías convertirlos una vez al principio y terminar con esto.
XXXXX

Hice una edición que simplifica significativamente la pregunta pero, al hacerlo, invalida esta respuesta. Lo siento, pero pensé que era por el bien general en general.
Mark Amery el

-1

Si lo entiendo correctamente, debe convertir el tipo (valor de carácter) que almacena en la lista de construcción al tipo (enumeración) que almacena en la lista de estado de construcción.

(Para cada estado en la lista de construcción // valor de carácter //, ¿existe el estado en la lista de estado de construcción // 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;
}

-1; Si bien mi edición de la pregunta ha invalidado ligeramente esta respuesta al eliminar toda referencia a Buildingla pregunta, esto ya estaba realmente roto . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))Es una tontería.
Mark Amery el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.