I am trying to filter on a list of people where dynamically the filters can change. So the moment I want to filter by gender and role, I give those two filters. The moment I want to change this to role only or change the value of the role, another filtering must be performed on the list with the new filter. As soon as filtering is done, it is checked whether the person meets all the filters. So, for example, the filtering is done on the gender with the value true and role number 4. Then only the person 'Meike' is returned.
I have tried the following code. This code adds each person again as soon as he meets each individual filter, so it is possible that a person appears twice in the list. Of course this can be solved by checking whether he already exists in the list, but I wonder if the code below is 'the way to go' for this problem.
List<Person> _people = new List<Person>();
_people.Add(new Person(1, "Bram", false, 4));
_people.Add(new Person(2, "Harry", false, 4));
_people.Add(new Person(3, "Meike", true, 4));
_people.Add(new Person(4, "Lisa", true, 3));
Console.WriteLine("Hello World!");
//
List<Person> secondPersonList = new();
Dictionary<string, object> secondFilter = new();
secondFilter.Add("Gender", true);
secondFilter.Add("Role", 3);
foreach (var filter in secondFilter)
{
if(filter.Key == "Gender")
{
foreach (var person in _people.FindAll(x => x.Gender == (bool)filter.Value))
secondPersonList.Add(person);
}
if (filter.Key == "Role")
{
foreach (var person in _people.FindAll(x => x.Role == (int)filter.Value))
secondPersonList.Add(person);
}
}
Console.WriteLine("Multiple filters");
foreach(Person person in secondPersonList)
{
Console.WriteLine($"Id: {person.Id}, Name: {person.Name}");
}
Person class:
{
public int Id { get; set; }
public string Name { get; set; }
public bool Gender { get; set; }
public int Role { get; set; }
public Person(int id, string name, bool gender, int role)
{
Id = id;
Name = name;
Gender = gender;
Role = role;
}
}
CodePudding user response:
The nice thing about LINQ is that you can add filters "on the fly". Since you clarified in the comments that you actually want to combine the filters with AND
instead of OR
, I suggest the following:
IEnumerable<Person> filtered = _people;
foreach (var filter in secondFilter)
{
switch (filter.Key)
{
case "Gender":
filtered = filtered.Where(x => x.Gender == (bool)filter.Value));
break;
case "Role":
filtered = filtered.Where(x => x.Role == (int)filter.Value));
break;
default:
// something went wrong, you might want to throw an exception here.
}
}
// This will evaluate the filters and materialize the result
var secondPersonList = filtered.ToList();
(For readability, I have changed your if
statements to a switch
statement, but the former will work as well.)