0

您好我正在尝试使用 Linq 从列表中删除“所有”实体。

问题:我正在搜索在我的数据库中具有某些证书的用户。事情是它逐行返回它们......但我需要检查的是:如果用户持有所有必需的证书。这应该针对我的 int 数组进行检查。

这是我的数组:[3,5,16],现在我想从列表中删除所有没有这三个的用户。代码中数组的名称是强制性的!

我回来的列表项看起来像这样

listitem.CertificateValue
listitem.Uid
listitem.NameOfPerson

所以基本上对于这个例子,彼得在列表中有三行,在这种情况下,所有行都需要留在列表中。但是 Philip 只有 2 行,因此应该删除这两行,因为他没有满足整个搜索条件。

也 copyOfMandatory 只是为了不弄乱原始集合并引起期望(集合大小已更改)。

foreach (var item in copyOfMandatory)
{
    if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue) 
                            || i.Uid == item.Uid))
    {
         mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
    }
}

UPDATE RemoveAll 就像一个魅力,它的 if 语句不能按预期工作。

这样做不会带走列表的任何部分,我从 && 而不是 || 开始 但是,只要他/她满足搜索条件,它就会杀死除了遇到的最后一个人之外的所有东西。

有人对如何做到这一点有提示吗?

4

4 回答 4

1

您的 ifAll条件已关闭。

if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue) 
                        || i.Uid == item.Uid))
{
     mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}

它需要与一个&&not an一起||,你应该打电话Any()而不是All()

if (!mandatoryusers.Any(i => mandatory.Contains(i.CertificateValue) 
                            && i.Uid == item.Uid))
{
    mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}

希望我能正确理解您的逻辑和问题。

于 2013-05-28T19:35:12.907 回答
1

您的All调用不够精细:它试图确保所有条目始终存在......并不是每个用户的所有条目都存在。

尝试将每个条目转换为字典:

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));
于 2013-05-28T19:35:36.307 回答
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));
于 2013-05-28T19:39:22.880 回答
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对象将包括您想要的所有用户。这是明确地选择您想要的值,而不是删除您不想要的值,imo 是一种更好的方法。请注意,这假设每个用户仅在列表中出现一次(即只有 3 个证书)

于 2013-05-28T19:46:17.103 回答