I am writing code to filter data on basis of attribute values. It is possible that the user can select multiple values.How can this be better?Models.Products filter(ViewModel.Filter search,IEnumerable<Models.Products> product){    if (search.filter!= null && search.filter.Count>0)        {             var f = search.First();             var tempProducts = products                               .Where(c => c.productattributes                                            .Where(a => a.AttributeId == f.Id && f.Value.Contains(a.Value))                                            .Any());             search.filter.Remove(f);             foreach (var fs in search)             {                var p = products.Where(c => c.productattributes.Where(a => a.AttributeId == fs.Id && fs.Value.Contains(a.Value)).Any());                tempProducts = tempProducts.Union(p);             }             products = tempProducts;        }}Filter View Model:public class Filters{    public long Id { get; set; }    public IEnumerable<string> Value { get; set; }}
Filtering data on basis of attribute values
c#;performance;linq
Your code appears to be incomplete but I've provided some ideas below.Filters ClassI'm looking at your Filters class:public class Filters{    public long Id { get; set; }    public IEnumerable<string> Value { get; set; }}From this, I am assuming that the purpose of this is to hold the Attribute Id (key) and Search Keywords (value). So, I would propose you just use a Dictionary<long, List<string>> -- note that I changed the type of your Search Keywords to a List as I am not seeing any reason within your code example as to why it should/would need to be an IEnumberable type.That would then change the method:Method renamedParameter updated to use Dictionary instead (per above)Here is the updated methodpublic IEnumerable<Product> FilterProductsByAttributeId(    Dictionary<long, List<string>> filters,    IEnumerable<Product> products){    // your method contents here}Filter MethodI'm not sure why you have a complicated initializer for your tempProducts, but maybe it can be improved to something like this?public IEnumerable<Product> FilterProductsByAttributeId(Dictionary<long, List<string>> filters, IEnumerable<Product> products){    if (products == null) throw new ArgumentNullException(nameof(products));    if (filters == null) throw new ArgumentNullException(nameof(filters));    IEnumerable<Product> result = new List<Product>();    foreach (var f in filters)    {        result = result.Union(products.Where(p => p.ProductAttributes            .Where(a => a.AttributeId == f.Key && f.Value.Contains(a.Value)).Any()));    }    return result;    }Alternatively you can use the Aggregate extension:return     filters        .Aggregate(            new List<Product>(),             (current, next) => current.Union(..)        );