Linq使用ALL语句删除结果

时间:2013-05-28 19:12:49

标签: c# asp.net-mvc linq

您好我正在尝试使用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语句一样无效。

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

任何人都有提示如何做到这一点?

4 个答案:

答案 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个证书)