179 votes

LINQ: "contient" et un Lambda de requête

J'ai une liste qui contient les énumérations, son standard Enum mais a un attribut attaché à elle, et d'une extension de la méthode qui retourne un CHAR de l'enum (voir ci-dessous - GetCharValue), l'extension fonctionne très bien.

Maintenant, j'ai (une autre méthode d'extension pour 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;
}

J'ai essentiellement besoin de dire "Retour" tout dans la requête, mais seulement si v. Statut est en buildingStatus... mais n'oubliez pas buildingStatus est un ILIST d'énumérations donc je DOIT appeler GetCharValue.

J'ai eu de l'aide précédemment avait, je crois, la syntaxe correcte est

buildingStatus.Contains (v.Status)   

mais le problème est ici que buildingStatus est un Ilist d'Énumérations donc je dois demander GetCharValue() sur chaque Élément de la Ilist avant de dire Contient..

Je pensais il y avait quelque chose de spécial moyen de le faire avec lambda à l'aide Contient comme - bien sûr, il ne fonctionne pas

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

Quelqu'un peut-il aider?

338voto

Rex M Points 80372

Utiliser Any() au lieu de Contient:

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

38voto

flq Points 11937

L'extension Linq méthode Tout pourrait travailler pour vous...

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

3voto

XXXXX Points 667

Je ne sais pas précisément ce que vous cherchez, 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 de chaîne de l'enum et produit le même résultat:

    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 à l'autre, mais je ne suis pas sûr de savoir comment elle est efficace; il peut juste créer une liste de derrière 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:

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

et de sauter la création de l' List<string> avec ConvertAll () au début.

-2voto

psabela Points 71

Si je comprends bien, vous avez besoin de convertir le type (char valeur) que vous stockez dans la Construction de liste pour le type (enum) que vous stockez dans buildingStatus liste.

(Pour chaque état dans le Bâtiment de la liste//valeur de caractère//, l'état existe dans le buildingStatus liste//valeur d'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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X