您好我正在尝试使用Linq从列表中删除“所有”实体。
问题:我正在搜索在我的数据库中拥有某些证书的用户。事情是它逐行返回....但我需要检查的是:如果用户持有所有必需的证书。这应该根据我的int数组进行检查。
这是我的数组:[3,5,16],现在我要删除列表中没有全部三个用户的所有用户。代码中数组的名称是必需!
我回来的列表项看起来像这样
listitem.CertificateValue
listitem.Uid
listitem.NameOfPerson
基本上,对于这个示例,Peter在列表中有三行,在这种情况下,所有行都需要保留在列表中。但菲利普只有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);
}
}
更新 RemoveAll就像一个魅力就像if语句一样无效。
这样做并没有带走列表的任何部分,我开始与&&而不是||但只要他/她满足搜索条件,它就会杀死所有人,只会遇到最后一个人。
任何人都有提示如何做到这一点?
答案 0 :(得分:1)
您的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);
}
希望我能正确理解你的逻辑和问题。
答案 1 :(得分:1)
您的All
电话不够精确:它正在尝试确保所有条目始终存在...并非所有条目PER 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));
答案 2 :(得分:1)
我会尝试类似的东西
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));
答案 3 :(得分:1)
您的if
声明不正确(如您所述) - 它正在尝试检查所有项目是否包含ID为mandatory
或的用户ID是当前项目。您应该做的是按用户ID 首先进行过滤,然后检查证书。
但这不是我想做的方式。我按用户对结果进行分组,然后检查证书
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个证书)