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)
Mark Smith
fuente

Respuestas:

320

Usar en Any()lugar de Contains():

buildingStatus.Any(item => item.GetCharValue() == v.Status)
Rex M
fuente
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)
flq
fuente
4

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

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

Cerebro blando
fuente
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.

XXXXX
fuente
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;
}
psabela
fuente
-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