Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding common components using LINQ

Tags:

c#

.net

linq

I am trying to find all the orders that have components in common and in addition the list of components in common:

Component Class:

public class Component
{
    public Component(string name)
    {
        this.Name = name;
    }
    public string Name { get; private set; }
}

Order Class:

internal class Order
{
    public Order(string name,List<Component> components)
    {
        this.Name = name;
        this.Components = components;
    }
    public string Name { get; private set; }

    public List<Component>Components { get; private set; }
}

For example:

var component1 = new Component("B1");
var component2 = new Component("B2");
var component3 = new Component("B3");
var component4 = new Component("B4");

var order1 = new Order("M1", new List<Component> { component2 });
var order2 = new Order("M2", new List<Component> { component1, component2, component3, component4 });
var order3 = new Order("M3", new List<Component> { component1, component2 });

var dependents = from cmp1 in order1.Components
                 join cmp2 in order2.Components
                 on cmp1.Name equals cmp2.Name
                 select new
                 {
                     order1Name = order1.Name,
                     order2Name = order2.Name,
                     ComponentName = cmp1.Name
                 };

var result = dependents.ToList();

The result is showing the correct information, the common component between order1 and order2 which is component2 ("B2").

How can I make it more general using orders list:

    var orders = new List<Order> { order1, order2, order3 };

I would like to get as result, for each 2 orders a list of components in common instead of doing it for each possible pair. I presume this is something like:

var allDependents = 
runs.ForEach(order=>order.Components)                
....
from cmp1 in order1.Components
join cmp2 in order2.Components
on cmp1.Name equals cmp2.Name
select new
{
    order1Name = order1.Name,
    order2Name = order2.Name,
    ComponentName = cmp1.Name
};

Additional Info:

As per the following picture, we can see for each 2 orders, a list of components

enter image description here

like image 805
ehh Avatar asked Dec 25 '22 07:12

ehh


1 Answers

Assuming all the names are unique you could do this.

var results = from o1 in orders
              from c1 in o1.Components
              from o2 in orders.SkipWhile(o => o.Name != o1.Name)
              from c2 in o2.Components
              where o1.Name != o2.Name && c1.Name == c2.Name
              select new 
              {  
                  Order1 = o1.Name,   
                  Order2 = o2.Name,   
                  Component = c1.Name   
              };

foreach(var r in results) Console.WriteLine(r);

It produces this output

{ Order1 = M1, Order2 = M2, Component = B2 }

{ Order1 = M1, Order2 = M3, Component = B2 }

{ Order1 = M2, Order2 = M3, Component = B1 }

{ Order1 = M2, Order2 = M3, Component = B2 }

like image 165
juharr Avatar answered Dec 27 '22 19:12

juharr