基于多个条件和多个值(未知值数)筛选列表

本文关键字:未知 筛选 列表 条件 于多个 | 更新日期: 2023-09-27 18:21:58

我有一个类User:

public class User{
    // some properties
    public string Name { get; set; }
    public int PerfLoc { get; set; }
    public bool Active { get; set; }
    // constructor would follow ..
}

我有一个类别PerfLoc:

public class PerfLoc{
    // some properties
    public string Number { get; set; }
    // constructor would follow ..
}

我有一个用户列表List<User> myUsers和一个列表List<PerfLoc> myPerfLoc。现在我想找到所有具有特定PerfLocmyUsers用户。所以我在myUsersmyPerfLoc中都有多个值。现在的练习是做一场比赛。我想了一些像这样的pseudeo代码:

List<User> filteredUser = new List<User> ();
foreach(PerfLoc currentPerfLoc in myPerfLoc){
    filteredUser += myUsers.Any(u => u.PerfLoc == currentPerfLoc.Number);
}
filteredUser = filterUser.Any(u => u.Active = true);
filteredUser.Sort();

在这里,我会在PerfLocActive(=多个标准)之后排序,也会在多个值(PerfLoc.Number的列表)之后排序。我从中看到了一些,其中,selectLINQ表达式,并认为我的上述方法可以用更短的方式表达。你会怎么表达?

基于多个条件和多个值(未知值数)筛选列表

您可以使用LINQ中的联接语句来完成此操作。与SQL类似,您可以将两个列表放在一起,并在属性或表达式上进行匹配。您也可以使用orderby进行排序。

以下是对匹配PerfLocs列表的活动用户的基本检查:

var filteredUser = from u in myUsers
                join p in myPerfLocs on u.PerfLoc equals p.Number.ToString()
                where u.Active == true
                orderby u // or u.Name if you need to
                select u;

由于您有条件地检查Active state和myPerfLocs,可能有一种方法可以在单个子句中进行检查,但它看起来会很混乱,所以我无论如何都会将其作为单独的检查保留-更短并不总是更干净。你可以创建一个结果IEnumerable,然后根据需要进行过滤:

bool checkActive = true;
// set up result list - variable needs to be IEnumerable<User>, not List<User>
var filteredUser = myUsers.AsEnumerable();
// add Active check if necessary
if (checkActive)
{
    filteredUser = filteredUser.Where(u => u.Active);
}
// check against PerfLoc list if necessary
if (myPerfLocs.Any())
{
    filteredUser = from u in filteredUser
                    join p in myPerfLocs on u.PerfLoc equals p.Number.ToString()
                    select u;
}
filteredUser = filteredUser.OrderBy(u => u); // or (u => u.Name) etc if you want

请参阅https://dotnetfiddle.net/hrnNmJ对于工作样品。

您可以使用Join。但请注意,在您提供的代码中,User.PerfLocintPerfLoc.Numberstring。如果真的是这样的话,那么你必须在下面的代码中添加一个转换。

var filteredUser = myUsers.Where(u => u.Active)
                          .Join(myPerfLoc, (u) => u.PerfLoc, 
                                           (p) => p.Number, 
                                           (u, p) => u);