2013-08-05 43 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