LINQ: "contient" et une requête Lambda


168

J'ai un List<BuildingStatus>appelé buildingStatus. Je voudrais vérifier si elle contient un état dont le code char (retourné par GetCharCode()) est égale à une variable, v.Status.

Existe-t-il un moyen de le faire, dans le sens du code (non compilant) ci-dessous?

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

Réponses:


320

Utilisez à la Any()place de Contains():

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

13
Agréable. Je me demande toujours pourquoi Linq ne fournit pas de Contains()méthode sur Terre , puis je me rends compte que c'est censé l'être à la Any()place. +1
Nolonar

38

La méthode d'extension Linq Any pourrait fonctionner pour vous ...

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

4

Voici comment vous pouvez utiliser Containspour réaliser ce que vous voulez:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) cela renverra une valeur booléenne.


3

Je ne sais pas exactement ce que vous recherchez, mais ce programme:

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

produit le résultat attendu:

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

Ce programme compare une représentation sous forme de chaîne de l'énumération et produit la même sortie:

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

J'ai créé cette méthode d'extension pour convertir un IEnumerable en un autre, mais je ne suis pas sûr de son efficacité; il peut simplement créer une liste dans les coulisses.

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

Ensuite, vous pouvez modifier la clause where en:

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

et ignorez la création du List<string>avec ConvertAll ()au début.


Merci larry qui a fonctionné, voici ce que j'ai fait en me référant à votre code ... Mais ce serait bien si possible si je n'avais pas à créer une nouvelle liste ???? // Utilisé ToList parce que c'est un ILIST et exécutez mon GetCharValue // cela produit une liste "NEW" avec mon caractère var statusStringList = building.ToList (). ConvertAll <char> (st => st.GetCharValue ()); var test = from v dans qry où statusStringList.Contains (v.Status) select v; Tout fonctionne, comme je l'ai dit, ce serait bien de ne pas avoir à faire une nouvelle liste ou d'utiliser un lambda à l'intérieur Contient mais semble que ce n'est PAS possible?
mark smith

Je suppose que la propriété status est une chaîne; vous devez donc convertir les énumérations d'état en chaînes pour chaque comparaison. Vous pourriez aussi bien les convertir une fois au début et en finir.
XXXXX

J'ai fait une modification qui simplifie considérablement la question mais, ce faisant, invalide en quelque sorte cette réponse. Désolé à ce sujet, mais j'ai pensé que c'était pour le plus grand bien dans l'ensemble.
Mark Amery

-1

Si je comprends bien, vous devez convertir le type (valeur char) que vous stockez dans la liste Building en le type (enum) que vous stockez dans la liste buildingStatus.

(Pour chaque statut de la liste Building // valeur de caractère //, le statut existe-t-il dans la liste buildingStatus // valeur d'énumération //)

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; alors que ma modification de la question a légèrement invalidé cette réponse en supprimant toute référence à Buildingla question, cela était déjà vraiment cassé . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))est un non-sens.
Mark Amery
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.