LINQ:比较两个列表和计数子集

时间:2015-02-03 14:17:19

标签: c# linq collections compare subset

我正在比较2个列表,只有当找到多个匹配项时,我才需要从主列表(allModules)中收集子集(modulesToDelete)的出现次数。 (allModules包含modulesToDelete)。 modulesToDelete中多次出现任何模块意味着共享这些模块。在modulesToDelete中出现一个模块意味着模块是隔离的并且可以安全删除(它只是找到了它自己)。我可以使用嵌套的foreach循环执行此操作,但这是因为我使用LINQ表达式(这不起作用)collect:

List<Module> modulesToDelete = { A, B, C, K }
List<string> allModules = {R, A, B, C, K, D, G, T, B, K }  // need to flag B and K

var mods = from mod in modulesToDelete
where allModules.Any(name => name.Contains(mod.Name) && mod.Name.Count() > 1)
select mod;

这是我的嵌套foreach循环,我想用LINQ表达式替换:

foreach (Module mod in modulesToDelete)
{
    int count = 0;
    foreach (string modInAllMods in allModules)
    {
        if (modInAllMods == mod.Name)
        {
            count++;
        }
    }

    if (count > 1)
    {
        m_moduleMarkedForKeep.Add(mod);
    }
    else if( count == 1)
    {
        // Delete the linked modules
    }
}

2 个答案:

答案 0 :(得分:0)

您可以使用类似于字典但允许多个相等键的查找,并返回IEnumerable<T>作为值。

var nameLookup = modulesToDelete.ToLookup(m => m.Name);
var safeToDelete = modulesToDelete.Where(m => nameLookup[m.Name].Count() == 1);
var sharedModules = modulesToDelete.Where(m => nameLookup[m.Name].Count() > 1);

编辑:但是,我看不出allModules是如何相关的。

可能更简单,并且您的样本数据具有所需的结果:

var mods = modulesToDelete.Where(m => allModules.Count(s => s == m.Name) > 1);

答案 1 :(得分:0)

解决这个问题的一种方法是使用Intersect函数, Intersection of two string array (ignore case)