我有2个自定义类型列表。它们有一个名为ItemID的公共元素,我希望得到它们存在于一个元素中的所有元素,而不是另一个元素。有没有人有任何想法?
我基本上需要与内连接相反,但只希望itemList中的元素不在itemCheckoutList中,或者如果IsComplete为真,它们可以在itemCheckoutList中。以下是我必须在IsComplete都为false的情况下获得所有内部联接的内部联接:
itemList.Join(itemCheckoutList,
i => i.ItemID,
ic => ic.ItemID,
(i, ic) => new { itemList = i, itemCheckoutList = ic }).Where(x => x.itemCheckoutList.IsComplete == false).ToList();
答案 0 :(得分:5)
我相信这就是你想要的。
itemList.Where(i => i.IsComplete ||
!itemCheckoutList.Any(ic => ic.ItemID == i.ItemID))
修改强>
根据您的评论,我认为这就是您想要的。
itemList.Where(i => !itemCheckoutList.Any(ic => ic.ItemID == i.ItemID &&
!ic.IsComplete))
修改强>
如果效率是一个问题,那么您需要为itemCheckoutList
创建一个可以重复使用的查找,或者只需将itemCheckoutList
更改为Dictionary<int, CheckOutItem>
,如CodeCaster建议的那样。这可以这样做。
// This should preferably be called just once but
// would need to be called whenever the list changes
var checkOutListLookup = itemCheckoutList.ToLookup(ic => ic.ItemID);
// and this can be called as needed.
var results = itemList.Where(i => !checkOutListLookup.Contains(i.ItemID) ||
checkOutListLookup[i.ItemID].IsComplete);
或者,如果你将它设为Dicionary<int, CheckOutItem>
,它将会是这样的。
var results = itemList.Where(i => !checkOutDictionary.ContainsKey(i.ItemID) ||
checkOutDictionary[i.ItemID].IsComplete);
答案 1 :(得分:1)
您还可以使用GroupJoin
:
itemList
.GroupJoin(itemCheckoutList, item => item.ItemID, itemCheckout => itemCheckout.ItemID, (item, itemCheckouts) => new {item, itemCheckouts})
.SelectMany(t => t.itemCheckouts.DefaultIfEmpty(), (t, itemCheckout) => new { t.item, itemCheckout })
.Where(t => t.item.IsComplete || t.itemCheckout == null)
.Select(t => t.item);
或与linq查询相同:
var l = from item in itemList
join itemCheckout in itemCheckoutList on item.ItemID equals itemCheckout.ItemID into gj
from itemCheckout in gj.DefaultIfEmpty()
where item.IsComplete || itemCheckout == null
select item;