如何比较linq中2个列表中子项的属性

时间:2013-08-05 02:11:07

标签: c# linq

我有以下对象:

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

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

现在,我有两个List对象,

List<ITray> selectedTrays
List<ITray> poolTrays

我想要做的是对于poolTrays中的每个元素,我想比较所选托盘列表中的Aisles。如果过道的全部匹配,我想将其添加到要返回的托盘列表中。 我只是想让自己陷入困境,试图让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]

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

目前,我在poolTray列表中传入(仅)[7,9],并在我的Linq查询中返回了2个实例

3 个答案:

答案 0 :(得分: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 :(得分: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();

答案 2 :(得分: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)性能,而不是List.Contains的O(n)。

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));
祝你好运。