Make Filter by one or more parameters

Viewed 52

I have List<Book> Books

public class Book
{
    public string Name { get; set; }
    public string Author { get; set; }
    public string Category { get; set; }
    public string Language { get; set; }
    public DateTime Publication_date { get; set; }
    public string ISBN { get; set; }
}

tried this, but it only work if all parameters matched

foreach (var item in Books)
{
    if ((!string.IsNullOrEmpty(name) && item.Name == name) 
      && (!string.IsNullOrEmpty(author) && item.Author == author) 
      && (!string.IsNullOrEmpty(category) && item.Category == category)
      && (!string.IsNullOrEmpty(language) && item.Language == language) 
      && (Publication_date.HasValue && item.Publication_date == Publication_date) 
      && (!string.IsNullOrEmpty(ISBN) && item.ISBN == ISBN))
    {
        Console.WriteLine(item);
    }
}

how to make filter by one or more parameters? like if i enter only "name" and "Language" it will print me the book where both parameters a matched (if string is null or empty then parameter should be skipped)

Thanks)

3 Answers

The logic is a touch complicated, but made simpler by use of continue.

foreach (var item in Books)
{
    if (!string.IsNullOrEmpty(name) && item.Name != name) continue;
    if (!string.IsNullOrEmpty(author) && item.Author != author) continue;
    if (!string.IsNullOrEmpty(category) && item.Category != category) continue;
    if (!string.IsNullOrEmpty(language) && item.Language != language) continue;
    if (Publication_date.HasValue  && item.Publication_Date != Publication_Date) continue;
    if (!string.IsNullOrEmpty(ISBN) && item.ISBN!= ISBN) continue;

    Console.WriteLine(item);
}

you want it in a form where each condition returns true if null, or true if match. Basically null/empty means anything is a match

like

(string.IsNullOrEmpty(name) || item.Name == name) 

then && them altogether

foreach (var item in Books)
{
    if ((string.IsNullOrEmpty(name) || item.Name == name) 
      && (string.IsNullOrEmpty(author) || item.Author == author) 
      && (string.IsNullOrEmpty(category) || item.Category == category)
      && (string.IsNullOrEmpty(language) || item.Language == language) 
      && (!Publication_date.HasValue || item.Publication_date == Publication_date) 
      && (string.IsNullOrEmpty(ISBN) || item.ISBN == ISBN))
    {
        Console.WriteLine(item);
    }
}

to be a little clearer you can do

bool IsMatchForFilter(string filter, string value) 
       => string.IsNullOrEmpty(filter) || filter == value;

then do

if(
   IsMatchForFilter(name, item.Name) 
   && IsMatchForFilter(author, item.Author)
  ...

Try it like this, use the OR (||) operator

foreach (var item in Books)
{
    if ((!string.IsNullOrEmpty(name) && item.Name == name) 
      || (!string.IsNullOrEmpty(author) && item.Author == author) 
      || (!string.IsNullOrEmpty(category) && item.Category == category)
      || (!string.IsNullOrEmpty(language) && item.Language == language) 
      || (Publication_date.HasValue && item.Publication_date == Publication_date) 
      || (!string.IsNullOrEmpty(ISBN) && item.ISBN == ISBN))
    {
        Console.WriteLine(item);
    }
}
Related