LINQ: "enthält" und eine Lambda-Abfrage

168

Ich habe einen List<BuildingStatus>angerufen buildingStatus. Ich möchte prüfen, ob es einen Status enthält, dessen Zeichencode (zurückgegeben von GetCharCode()) einer Variablen entspricht v.Status.

Gibt es eine Möglichkeit, dies im Sinne des folgenden (nicht kompilierten) Codes zu tun?

buildingStatus.Contains(item => item.GetCharValue() == v.Status)
Mark Smith
quelle

Antworten:

320

Verwenden Sie Any()anstelle von Contains():

buildingStatus.Any(item => item.GetCharValue() == v.Status)
Rex M.
quelle
13
Nett. Ich frage mich immer wieder, warum Linq auf der Erde keine Contains()Methode anbietet , und dann wird mir klar, dass es Any()stattdessen so sein soll . +1
Nolonar
38

Die Linq-Erweiterungsmethode Jeder könnte für Sie arbeiten ...

buildingStatus.Any(item => item.GetCharValue() == v.Status)
flq
quelle
4

So können Sie Containserreichen, was Sie wollen:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) Dies gibt einen Booleschen Wert zurück.

Soft-Brain
quelle
3

Ich bin mir nicht sicher, wonach Sie suchen, aber dieses Programm:

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

erzeugt die erwartete Ausgabe:

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

Dieses Programm vergleicht eine Zeichenfolgendarstellung der Aufzählung und erzeugt dieselbe Ausgabe:

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

Ich habe diese Erweiterungsmethode erstellt, um eine IEnumerable in eine andere zu konvertieren, bin mir aber nicht sicher, wie effizient sie ist. Möglicherweise wird nur eine Liste hinter den Kulissen erstellt.

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

Dann können Sie die where-Klausel in Folgendes ändern:

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

und überspringen Sie das Erstellen des List<string>mit ConvertAll ()am Anfang.

XXXXX
quelle
Vielen Dank, Larry, das hat funktioniert. Hier ist, was ich getan habe, indem ich auf Ihren Code verwiesen habe. Aber es wäre schön, wenn ich keine neue Liste erstellen müsste. // ToList verwendet, da es sich um eine ILIST handelt und mein GetCharValue ausgeführt wird // dies erzeugt eine "NEUE" Liste mit dem var statusStringList = building.ToList () meines Zeichens. ConvertAll <char> (st => st.GetCharValue ()); var test = von v in qry wobei statusStringList.Contains (v.Status) v auswählt; Alles funktioniert, wie ich schon sagte, es wäre schön, keine neue Liste zu erstellen oder ein Lambda in Contains zu verwenden, aber es scheint NICHT möglich zu sein?
Mark Smith
Ich gehe davon aus, dass die Statuseigenschaft eine Zeichenfolge ist. Sie müssen daher die Statusaufzählungen für jeden Vergleich in Zeichenfolgen konvertieren. Sie können sie auch gleich zu Beginn einmal konvertieren und damit fertig sein.
XXXXX
Ich habe eine Bearbeitung vorgenommen, die die Frage erheblich vereinfacht, diese Antwort jedoch irgendwie ungültig macht. Tut mir leid, aber ich dachte, es wäre insgesamt zum Wohle der Allgemeinheit.
Mark Amery
-1

Wenn ich das richtig verstehe, müssen Sie den Typ (Zeichenwert), den Sie in der Gebäudeliste speichern, in den Typ (Aufzählung) konvertieren, den Sie in der Gebäudestatusliste speichern.

(Existiert der Status für jeden Status in der Gebäudeliste // Zeichenwert // in der Gebäudestatusliste // Aufzählungswert //)

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
quelle
-1; Während meine Bearbeitung der Frage diese Antwort leicht ungültig gemacht hat, indem alle Verweise auf Buildingaus der Frage entfernt wurden, war dies bereits wirklich kaputt . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))ist Unsinn.
Mark Amery