我正在尝试查找所有具有共同组件的订单以及共同的组件列表:
组件类:
public class Component
{
public Component(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
订单类:
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; }
}
例如:
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();
结果显示正确的信息,order1
和order2
之间的公共组件component2
(&#34; B2&#34;)。
如何使用订单列表使其更通用:
var orders = new List<Order> { order1, order2, order3 };
我想得到结果,对于每2个订单,共同的组件列表而不是为每个可能的对执行。 我认为这就像:
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
};
其他信息:
根据下图,我们可以看到每两个订单,一个组件列表
答案 0 :(得分:4)
假设所有名称都是唯一的,您可以这样做。
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);
它产生此输出
{Order1 = M1,Order2 = M2,Component = B2}
{Order1 = M1,Order2 = M3,Component = B2}
{Order1 = M2,Order2 = M3,Component = B1}
{Order1 = M2,Order2 = M3,Component = B2}
答案 1 :(得分:4)
一种可行的有效方法是使用半连接以及其他标准:
var orders = new List<Order> { order1, order2, order3 };
var orderComponents = from order in orders
from component in order.Components
select new { order, component };
var dependents =
from e1 in orderComponents
join e2 in orderComponents on e1.component.Name equals e2.component.Name
where e2.order != e1.order && e2.order.Name.CompareTo(e1.order.Name) > 0
select new
{
order1Name = e1.order.Name,
order2Name = e2.order.Name,
ComponentName = e1.component.Name
};
唯一需要提及的细节是标准e2.order != e1.order && e2.order.Name.CompareTo(e1.order.Name) > 0
。第一个条件从左侧排除顺序,而第二个条件排除重复,如{M2,M1}。
答案 2 :(得分:1)
我对Fluent Linq语法更有经验,您可以在其中执行所需操作:
var orders = new[] { order1, order2, order3 };
var dependents = orders.SelectMany(order =>
orders
.Where(other => other.Name != order.Name)
.SelectMany(other => other.Components.Intersect(order.Components)
.Select(c => new { order, other, component = c }))
).ToList();
答案 3 :(得分:1)
您可以使用查找(警告:未经测试的代码):
var lookup = orders
.SelectMany(ord => ord.Components.Select(cmp => new { Order = ord, Component = cmp)
.ToLookup(obj => obj.Component /* or obj.Component.Name, if you prefer */)
.Where(lkp => lkp.Count() > 1);
foreach(var orders in lookup)
{
// orders.Key is the component, orders is an Enumeration of orders containing that component.
}
答案 4 :(得分:0)
如果您在IEquatable<T>
和Component
上实施Order
,并覆盖object.Equals()
(作为良好做法),您可以执行以下操作:
var ordersA = new List<Order> { order1, order2, order3 };
var ordersB = new List<Order> { order2, order3 };
bool equal = ordersA.Equals(ordersB);
&#39;等于&#39; Component
上的实现还允许您通过使用集合交集来获取通用组件,如:
var compA = new List<Component> { c1, c2, c3};
var compB = new List<Component> { c2, c3};
var commonComponents = compA.Intersect(compB);
您甚至可以在Intersect
列表中使用Order
。