mameesh
mameesh

Reputation: 3761

Is there a way to combine these two LINQ statements into one

I need to produce 2 separate lists out of 1 list. If company.IsNone is true, I want all employees added to the first list that match the locationsToCompare list, if its not true, I want all of the employees that don't match the locationsToCompare list. This is the exact opposite when populating the second list. Is there a way to combine these two if statements into one, or am I forced to have two separate to populate the two lists?

var noneEmployees = company.IsNone
       ? employees.Where(employee => locationsToCompare.Any(x => x.ID == employee.LocationID)).ToList()
       : employees.Where(employee => locationsToCompare.All(x => x.ID != employee.LocationID)).ToList();

var locationEmployees = company.IsNone
       ? employees.Where(employee => locationsToCompare.All(x => x.ID != employee.LocationID)).ToList()
       : employees.Where(employee => locationsToCompare.Any(x => x.ID == employee.LocationID)).ToList();

Upvotes: 3

Views: 123

Answers (3)

Leigh Shepperson
Leigh Shepperson

Reputation: 1053

Try something like this, using Except so you don't have to repeat all the code:

public class Company
{
    public bool IsNone { get; set; }
}

public class Employee
{
    public int LocationID { get; set; }
}

public class Location
{
   public int ID { get; set; }
}

Operation

var locationsToCompare = new List<Location> { new Location() { ID = 1 }, new Location() { ID = 2 } };

var employees = new List<Employee> { new Employee() { LocationID = 1 }, new Employee { LocationID = 2 }, new Employee { LocationID = 1}, new Employee { LocationID = 5 } };

var company = new Company();

company.IsNone = false;

var noneEmployees = company.IsNone
                  ? employees.Where(employee => locationsToCompare.Any(x => x.ID == employee.LocationID)).ToList()
                  : employees.Where(employee => locationsToCompare.All(x => x.ID != employee.LocationID)).ToList();

var locationEmployees = employees.Except(noneEmployees).ToList();

Upvotes: 1

ΩmegaMan
ΩmegaMan

Reputation: 31596

The group of employees is dependent on whether a company IsNone flag is set.

But before figuring that out, let us group the employees using the ToLookup(TSource, TKey) which is a dictionary/grouping type lookup where the key is whether the employee is in the locationsToCompare list.

Once the lookup is setup, we can the pipe in the company IsNone flag and extract the employees.


Example Setup Data

var employees = new List<Employee>
         { new Employee { LocationID = 1, Name = "Hamilton" },
           new Employee { LocationID = 2, Name = "Joe"      },
           new Employee { LocationID = 1, Name = "Frank"    },
           new Employee { LocationID = 5, Name = "Reynolds" } };

var company = new Company() { IsNone = false };

Locations

var locationsToCompare = new List<Location> { new Location() { ID = 1 },
                                              new Location() { ID = 2 } };

Contains

I will eventually use a Contains in lieu of a where clause so I will distill the locationsToCompare into a list of ids.

var LocationIds = locationsToCompare.Select(ltc => ltc.ID);

This step could be skipped, but I believe it makes it easier to maintain.

ToLookUp

Now we use the ToLookup and then extract our lists based on company 'IsNone' flag:

var empLookup = employees.ToLookup(emp => LocationIds.Contains(emp.LocationID));

var noneEmployees     = empLookup[company.IsNone].ToList();
var locationEmployees = empLookup[!company.IsNone].ToList();

Result

enter image description here


What did the lookup look like? For it did the heavy lifting for us.

enter image description here

Upvotes: 2

Ties
Ties

Reputation: 1245

You can also extract the location ids into a separate list, and use that in the Where() clause, together with an xor for the IsNone. Combining that with the Except() operator solution of @leigh-shepperson, you get this:

var locationIds = locationsToCompare.Select(location => location.ID);
noneEmployees = employees.Where(employee => !company.IsNone ^ locationIds.Contains(employee.LocationID));
locationEmployees = employees.Except(noneEmployees);

I don't know if that's the most readable solution, but it makes it possible to make it shorter.

Upvotes: 1

Related Questions