Search code examples
c#linq

How to find the matching element in a list from different list? in C#


How to find the matching element in array from different array? in C#

I have different varities of products and dynamically created attributes of every variety

public class SingleVariety
    {
        [JsonProperty("varietyId")]
        public int VarietyId { get; set; }

        [JsonProperty("varietyName")]
        public string VarietyName { get; set; }

        [JsonProperty("sku")]
        public string Sku { get; set; }

        public List<SingleAttribute> Attributes { get; set; }= new List<SingleAttribute>();

    }

   public class SingleAttribute
    {

        [JsonProperty("attributeName")]
        public string AttributeName { get; set; }

        [JsonProperty("attributeValue")]
        public string AttributeValue { get; set; }

        [JsonProperty("varietyId")]
        public int VarietyId { get; set; }

    }

and I have a filter array and trying to determine the selected variety based on the selection of attributes

sample variety model


 var varities = new List<SingleVariety>() { 
                new SingleVariety { 
                    Sku="testsku", VarietyId=1, VarietyName="test 1", 
                Attributes = new List<SingleAttribute> 
                { new SingleAttribute { AttributeName = "Size", AttributeValue="Large" },
                    new SingleAttribute{ AttributeName = "Color", AttributeValue = "Red"} 
                }},
                new SingleVariety {
                    Sku="testsku2", VarietyId=2, VarietyName="test 2",
                Attributes = new List<SingleAttribute>
                { new SingleAttribute { AttributeName = "Size", AttributeValue="Small" },
                    new SingleAttribute{ AttributeName = "Color", AttributeValue = "Red"}
                }},
                new SingleVariety {
                    Sku="testsku3", VarietyId=3, VarietyName="test 3",
                Attributes = new List<SingleAttribute>
                { new SingleAttribute { AttributeName = "Size", AttributeValue="Very Large" },
                    new SingleAttribute{ AttributeName = "Color", AttributeValue = "Black"}
                }}

            };

sample filter array

 var filterObject = new List<SingleAttribute> { 
                new SingleAttribute { AttributeName = "Size", AttributeValue="Large" },
            new SingleAttribute{ AttributeName = "Color", AttributeValue = "Red"} 
            };

variety with variety id 1 should be found because the filter object contains size=large, and color=red anyone can help me this?

I have used predicates, linq but I was not successfull


Solution

  • One (flexible) way of doing this would be to chain your queries:

    //Start with the whole set
    var results = (IEnumerable<SingleVariety>)varities;
    
    for (int i = 0; i < filterObject.Count; i++)
    {
        var filter = filterObject[i];
        //Refine with each attribute match
        results = results.Where(i => i.Attributes.FirstOrDefault(a => a.AttributeName == filter.AttributeName)?.AttributeValue == filter.AttributeValue);
    }
    

    If we inspect the output:

    Console.WriteLine($"Count: {results.Count()}");
    foreach (var result in results)
    {
        Console.WriteLine($"Name: {result.VarietyName}, Id: {result.VarietyId}");
    }
    

    We get the following:

    Count: 1
    Name: test 1, Id: 1
    

    We cast it to the IEnumerable<SingleVariety> interface so that the chaining can work since the Linq methods will return that type.

    A couple of things worth noting is that this will support any number of filters but it will be an and operation.

    Technically, you don't need the filter variable. You could just do it inline but I like to write code this way for clarity.