LINQ: "contains" and a Lambda query

I have a List<BuildingStatus> called buildingStatus. I'd like to check whether it contains a status whose char code (returned by GetCharCode()) equals some variable, v.Status.

Is there some way of doing this, along the lines of the (non-compiling) code below?

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

Solution 1:

Use Any() instead of Contains():

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

Solution 2:

The Linq extension method Any could work for you...

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

Solution 3:

Here is how you can use Contains to achieve what you want:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) this will return a Boolean value.

Solution 4:

I'm not sure precisely what you're looking for, but this program:

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

produces the expected output:

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

This program compares a string representation of the enum and produces the same output:

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

I created this extension method to convert one IEnumerable to another, but I'm not sure how efficient it is; it may just create a list behind the scenes.

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

Then you can change the where clause to:

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

and skip creating the List<string> with ConvertAll () at the beginning.