Reputation: 20279
I have a class User
:
public class User{
// some properties
public string Name { get; set; }
public int PerfLoc { get; set; }
public bool Active { get; set; }
// constructor would follow ..
}
Than I have a class PerfLoc
:
public class PerfLoc{
// some properties
public string Number { get; set; }
// constructor would follow ..
}
I have a list of users List<User> myUsers
and a list List<PerfLoc> myPerfLoc
. Now I want to find all users of myUsers
which have a certain PerfLoc
. So I have multiple values in myUsers
and multiple values in myPerfLoc
. The exercise now is to make a match. I thought about some sort of pseudeo code like this:
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();
Here I'd have sorted after PerfLoc
and Active
(= multiple criteria) and also after multiple values (list of PerfLoc.Number
). I saw some from, where, select LINQ expressions and thought that my approach above could be expressed in a shorter way. How would you express that?
Upvotes: 0
Views: 8075
Reputation: 16609
You can do this using a join statement in LINQ. Similar to in SQL you put the two lists together and match them on a property or expression. You can also sort using orderby.
The following is a basic check for Active Users matching a list of 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;
As you are conditionally checking Active state and against myPerfLocs, there may be a way to do it in a single clause but it would look messy, so I would keep it as separate checks anyway - shorter is not always cleaner. You can create a result IEnumerable and then filter that as necessary:
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
See https://dotnetfiddle.net/hrnNmJ for a working sample.
Upvotes: 1
Reputation: 101032
You can use Join
. But note that in the code you provided User.PerfLoc
is int
and PerfLoc.Number
is string
. If this is really the case then you have to add a conversion to the code below.
var filteredUser = myUsers.Where(u => u.Active)
.Join(myPerfLoc, (u) => u.PerfLoc,
(p) => p.Number,
(u, p) => u);
Upvotes: 1