如何在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查询
这样的东西应该可以工作:
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()));