2013-08-05 30 views
3

我有以下的比较对象一个子项的属性:如何在2只列出了LINQ

public interface ITray 
{ 
int OrderNo {get; set;} 
IEnumerable<ITrayItem> TrayItems {get;} 
} 

public interface ITrayItem 
{ 
int Aisle {get; set;} 
} 

现在,我有两个表的对象,

List<ITray> selectedTrays 
List<ITray> poolTrays 

我所试图做的是对于poolTrays中的每个元素,我想比较所选纸盘列表中的通道。如果所有的通道匹配,我想将它添加到要返回的托盘列表中。 我只是在试图让linq与查询列表中的集合的属性并返回匹配的列表中的项目打结。

这是我的时刻:

List<int> selectedAisles = (from tray in selectedTrays 
          from item in tray.TrayItems 
          select item.Aisle).Distinct().ToList() 

List<ITray> trayswithMatchingAisles = 
      (from t in poolTrays 
      from item in t.TrayItems 
      where selectedAisles.Contains(item.Aisle) 
      select t).ToList(); 

所以,如果我已经选择托盘A,B,C与在括号过道 A [1,2,3] B [4,5 ,6] c [7,8,9]

然后在aisles [7,9]中使用TrayItems的poolTray应该成功返回,但不应返回带有TrayItems [7,8,9,10]的池托盘在列表中。

目前,我传递(只)[7,9]在我poolTray名单,和它的两个实例都在我的LINQ查询返回

回答

2

像这样的东西应该工作:

List<int> selectedAisles = 
    (from tray in selectedTrays 
    from item in tray.TrayItems 
    select item.Aisle) 
    .Distinct().ToList(); 

List<ITray> trayswithMatchingAisles = 
    (from t in poolTrays 
    where t.TrayItems.Select(i => i.Aisle) 
      .All(a => selectedAisles.Contains(a)) 
    select t) 
    .ToList(); 

但是,这可以简化为:

List<ITray> trayswithMatchingAisles = 
    (from t in poolTrays 
    where t.TrayItems.Select(i => i.Aisle) 
      .All(a => selectedTrays 
       .SelectMany(s => s.TrayItems) 
       .Select(i => i.Aisle) 
       .Contains(a)) 
    select t) 
    .ToList(); 

或者这样:

List<ITray> trayswithMatchingAisles = poolTrays 
    .Where(t => t.TrayItems 
     .Select(i => i.Aisle) 
     .All(a => selectedTrays 
       .SelectMany(s => s.TrayItems) 
       .Select(i => i.Aisle) 
       .Contains(a))) 
    .ToList(); 
+0

对不起,刚刚意识到一个不是c。 – jazza1000

+0

干杯pswg,你的答案对我来说是诀窍 – jazza1000

+0

@ jazza1000你能测试我的答案吗?它工作吗? (刚刚编辑)。 –

2
var result = poolTrays.Where(x => selectedTrays.Any(z=>z.TrayItems.Select(y => y.Aisle) 
                  .Intersect(x.TrayItems.Select(k => k.Aisle)) 
                  .Count() == x.TrayItems.Count())); 
+1

+1是的,这是一个好方法。如果OP的'ITrayItem'实现覆盖'Equals'方法,你的原始版本就可以工作。 –

+0

@ p.s.w.g谢谢:) –

+0

对不起KK,这个版本运行良好,以前的版本不会为我编译。 – jazza1000

2

我想你需要使用“SelectMany”扩展名,这是为了返回列表列表的平面查询。

例如:

var distinctSelectedItems = selectedTrays.SelectMany(t => t.TrayItems).Select(ti => ti.Aisle).Distinct(); 
bool success = poolTrays.SelectMany(t => t.TrayItems).All(ti => distinctSelectedItems.Contains(ti.Aisle)); 

您还可以创建一个HashSet,才能有O(1)性能,而不是为O(n)为List.Contains。

var distinctSelectedItems = new HashSet<int>(selectedTrays.SelectMany(t => t.TrayItems).Select(ti => ti.Aisle)); 
bool success = poolTrays.SelectMany(t => t.TrayItems).All(ti => distinctSelectedItems.Contains(ti.Aisle)); 

祝你好运。

+0

这也适用于我的代码。 – jazza1000