LINQ: "contains"和Lambda查询

189

我有一个名为buildingStatusList<BuildingStatus>。我想检查它是否包含一个状态,其字符代码(由GetCharCode()返回)等于某个变量v.Status

是否有一种方法可以实现这一点,类似于以下(不能编译的)代码?

buildingStatus.Contains(item => item.GetCharValue() == v.Status)
6个回答

367

使用Any()代替Contains()

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

39

Linq 扩展方法 Any 可以帮助你...

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

6

以下是如何使用Contains来实现你想要的功能:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status)这将返回一个布尔值。


3

我不确定您具体需要什么,但是这个程序:

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

能够产生预期的输出结果:

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

这个程序比较枚举类型的字符串表示,并产生相同的输出:

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

我创建了这个扩展方法来将一个IEnumerable转换成另一个,但是我不确定它的效率如何;它可能只是在幕后创建了一个列表。
public static IEnumerable <TResult> ConvertEach (IEnumerable <TSource> sources, Func <TSource,TResult> convert)
{
    foreach ( TSource source in sources )
        yield return convert (source);
}

然后你可以将where子句更改为:
where statusList.ConvertEach <string> (status => status.GetCharValue()).
    Contains (v.Status)

并跳过在开头使用 ConvertAll() 创建 List<string>


谢谢Larry,它起作用了,这是我通过参考您的代码所做的...但如果可能的话,不创建新列表会更好吗?//使用ToList,因为它是一个ILIST并运行我的GetCharValue //这将产生一个“NEW”列表与我的字符 var statusStringList = building.ToList().ConvertAll<char>(st => st.GetCharValue()); var test = from v in qry where statusStringList.Contains(v.Status) select v;所有工作都正常,如我所说,不必做一个新列表或在Contains中使用lambda会更好,但似乎不可能? - mark smith
我假设状态属性是一个字符串;因此,你需要将状态枚举转换为字符串以进行每次比较。最好在开始时将它们转换一次,然后就可以了。 - XXXXX
我已经编辑了问题,使其大大简化,但同时也使这个回答有点失效。对此我感到抱歉,但我认为这样做对整体有利。 - Mark Amery

0
var depthead = (from s in db.M_Users
                  join m in db.M_User_Types on s.F_User_Type equals m.UserType_Id
                  where m.UserType_Name.ToUpper().Trim().Contains("DEPARTMENT HEAD")
                  select new {s.FullName,s.F_User_Type,s.userId,s.UserCode } 
               ).OrderBy(d => d.userId).ToList();

Model.AvailableDeptHead.Add(new SelectListItem { Text = "Select", Value = "0" });
for (int i = 0; i < depthead.Count; i++)
    Model.AvailableDeptHead.Add(new SelectListItem { Text = depthead[i].UserCode + " - " + depthead[i].FullName, Value = Convert.ToString(depthead[i].userId) });

在这里,我正在尝试将用户类型表中的userType与用户表匹配,以收集部门负责人姓名。希望成功。 - mohit vijay chaudhari

-2

如果我理解正确,您需要将存储在 Building 列表中的类型(char 值)转换为存储在 buildingStatus 列表中的类型(枚举)。

(对于 Building 列表中的每个状态//字符值//,该状态是否存在于 buildingStatus 列表中//枚举值//)

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;虽然我对问题进行的编辑已经将所有关于“Building”的引用从问题中删除,但这已经是非常错误的foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))是无意义的。 - Mark Amery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接