如何在linq中比较两个列表中一个子项的属性

本文关键字:一个 属性 列表 两个 比较 linq | 更新日期: 2023-09-27 18:26:18

我有以下对象:

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中的每个元素,我想比较所选托盘列表中的通道。如果通道的所有匹配,我想将其添加到要返回的托盘列表中。我只是有点纠结,试图让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、CA[1,2,3]B[4,5,6]c[7,8,9]

则通道[7,9]中有TrayItems的池托盘应成功返回,但列表中不应返回带有TrayItems[7,8,9,10]的池托盘。

目前,我正在poolTray列表中传递[7,9],并且在我的Linq查询

如何在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();

我认为您需要使用"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));

祝你好运。

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()));