Linq用ALL语句删除结果
本文关键字:删除 结果 语句 ALL Linq | 更新日期: 2023-09-27 18:15:58
你好,我正在尝试使用Linq从列表中删除"所有"实体。
问题:我正在搜索数据库中具有某些证书的用户。它会逐行返回....但是我需要检查的是:用户是否持有所有必需的证书。这应该根据我的int数组进行检查。
这是我的数组:[3,5,16],现在我想从列表中删除所有没有所有三个用户的用户。代码中的数组名称必选!
我得到的列表看起来像这样
列。CertificateValue
列。Uid
列。NameOfPerson
基本上在这个例子中,Peter在列表中有三行,在这个例子中,所有的行都需要留在列表中。但是Philip只有2行,因此这两行都应该被删除,因为他没有满足全部搜索条件。
copyOfMandatoryis只是为了不与原始集合混淆并导致期望(集合大小更改)。
foreach (var item in copyOfMandatory)
{
if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue)
|| i.Uid == item.Uid))
{
mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}
}
如果if语句没有像预期的那样工作,RemoveAll就会像魅力一样工作。
这样做不会拿走列表的任何部分,我以&&而不是||但是当它这样做时,它会杀死除了最后遇到的人以外的所有人,只要他/她满足搜索条件。
谁有一个提示如何做到这一点?
我会尝试这样做
var uIdToRemove = mandatoryusers.GroupBy(m => m.Uid)
.Where(g => mandatory.Except(g.Select(s => s.CertificateValue)).Any())
.Select(g => g.Key).ToList();
mandatoryusers.RemoveAll(x => uidToRemove.Contains(x.Uid));
您的All
调用不够细粒度:它试图确保所有条目在任何时候都存在…并不是每个USER都存在。
尝试将每个条目转换为字典:
var dict = new Dictionary<int, List<ItemType>>();
foreach (var mandatoryItem in mandatoryItems)
{
List<ItemType> itemTypeValue = null;
if (!dict.TryGetValue(mandatoryItem.Uid, out itemTypeValue)
{
itemTypeValue = new List<ItemType>();
dict.Add(mandatoryItem.Uid, itemTypeValue);
}
itemTypeValue.Add(mandatoryItem);
}
现在您在Uid键处拥有了所有ItemType。从这里开始,使用LINQ:
mandatoryusers = mandatoryusers.Where(i => dict[i.Uid].All(x => mandatory.Contains(x.CertificateValue));
您的if All
条件已关闭。
if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue)
|| i.Uid == item.Uid))
{
mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}
需要使用&&
而不是||
,您应该调用Any()
而不是All()
if (!mandatoryusers.Any(i => mandatory.Contains(i.CertificateValue)
&& i.Uid == item.Uid))
{
mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}
希望我正确理解了你的逻辑和问题。 您的if
语句不正确(如您所述)-它试图检查是否所有项目都包含mandatory
或中用户id为当前项目的id证书。您应该做的是首先通过userid 进行过滤,然后检查证书。但我不会这么做。我将按用户对结果进行分组,然后检查证书
var usersWithAllCertificates = mandatoryUsers.GroupBy(mu => mu.Uid)
//Select the ones that have all 3 certificates
.Where(g => g.Select(u => u.CertificateValue)
.Intersect(mandatory).Count() == 3)
.Select(g => g.ToList());
Intersect
操作符将两个列表合并,结果将是两个列表中相同的项。因此,如果用户拥有所有3个证书(3,5和16),相交的结果将是3项。usersWithAllCertificates
对象将包含所需的所有用户。这是显式地选择您想要的值,而不是删除您不想要的值,我认为这是一种更好的方法。注意,这假设每个用户只在列表中出现一次(即只有3个证书)