LINQ: "contains" and a Lambda query

267,370

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.

Share:
267,370

Related videos on Youtube

mark smith
Author by

mark smith

Updated on September 05, 2020

Comments

  • mark smith
    mark smith over 3 years

    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)
    
  • mark smith
    mark smith over 14 years
    Thanks larry that worked, here is what i did by refering to your code... But it would be nice if possible if i didn't have to create a new list???? // Used ToList because its an ILIST and run my GetCharValue // this produces a "NEW" list with my char's var statusStringList = building.ToList().ConvertAll<char>(st => st.GetCharValue()); var test = from v in qry where statusStringList.Contains(v.Status) select v; All works, as i say it would be nice not having to do a new list or using a lambda inside Contains but appears its NOT possible?
  • XXXXX
    XXXXX over 14 years
    I assume the status property is a string; you therefore have to convert the status enums to strings for each comparison. You might as well convert them once at the beginning and be done with it.
  • Nolonar
    Nolonar over 8 years
    Nice. I keep wondering why on Earth Linq doesn't provide a Contains() method, and then I realize it's supposed to be Any() instead. +1
  • Mark Amery
    Mark Amery over 6 years
    I've made an edit that significantly simplifies the question but, in doing so, sort-of-invalidates this answer. Sorry about that, but I figured it was for the greater good overall.
  • Mark Amery
    Mark Amery over 6 years
    -1; while my edit to the question has slightly invalidated this answer by removing all reference to Building from the question, this was already really broken. foreach(Enum value in Enum.GetValues(typeof(buildingStatus))) is nonsense.
  • mohit vijay chaudhari
    mohit vijay chaudhari over 3 years
    here I'm try to match my userType form user type table to user table for t collect department head name hope sa