如何确保List <string>只包含序列中的每个字符串</string>

时间:2012-05-09 00:02:51

标签: c# linq

假设我有一个字符串列表,如下所示:

var candidates = new List<String> { "Peter", "Chris", "Maggie", "Virginia" };

现在,我想验证另一个List<String>,让我们称之为list1,只包含每个候选人一次。 我怎么能这样做,简单?我想我可以使用Intersect()。我也希望找到失踪的候选人。

private bool ContainsAllCandidatesOnce(List<String> list1)
{
     ????
}


private IEnumerable<String> MissingCandidates(List<String> list1)
{
     ????
}

订单无关紧要。

7 个答案:

答案 0 :(得分:5)

这在速度方面可能不是最优的,但两个查询都足够短,可以放在一行,并且易于理解:

private bool ContainsAllCandidatesOnce(List<String> list1)
{
    return candidates.All(c => list1.Count(v => v == c) == 1);
}

private IEnumerable<String> MissingCandidates(List<String> list1)
{
    return candidates.Where(c => list1.Count(v => v == c) != 1);
}

答案 1 :(得分:2)

我们在此谈论ExceptIntersectDistinct。我可以使用带表达式的lamba运算符,但它必须遍历每个项目。该功能可用于预定义的功能。

第一种方法

var candidates = new List<String> { "Peter", "Chris", "Maggie", "Virginia" };

private bool ContainsAllCandidatesOnce(List<String> list1)
{
    list1.Intersect(candidates).Distinct().Any();
}

这将给list1中的任何元素在候选列表中是常见的,或者你可以用其他方式执行

candidates.Intersect(list1).Distinct().Any();
第二种方法

private IEnumerable<String> MissingCandidates(List<String> list1)
{
    list1.Except(candidates).AsEnumerable();
}

这将删除list1中候选人中的所有元素。如果您想以其他方式做到这一点

candidates.Except(list1).AsEnumerable();

答案 2 :(得分:1)

这应该非常有效:

IEnumerable<string> strings  = ...

var uniqueStrings = from str in strings
                    group str by str into g
                    where g.Count() == 1
                    select g.Key;

var missingCandidates = candidates.Except(uniqueStrings).ToList();
bool isValid = !missingCandidates.Any();
  1. 过滤掉重复次数。
  2. 确保所有候选项都出现在已过滤的集合中。

答案 3 :(得分:1)

GroupJoin是这项工作的正确工具。来自msdn

  

GroupJoin生成分层结果,表示元素   从外部与匹配元素的集合配对   内。 GroupJoin使您可以将结果基于一整套   匹配外部的每个元素。

     

如果外部的给定元素的内部没有相关元素,则该元素的匹配序列将为空   仍然会出现在结果中。

因此,对于源中的每个项目,GroupJoin将找到目标的任何匹配项。如果在目标中找不到匹配项,则不会过滤源中的项目。相反,他们匹配一个空组。

Dictionary<string, int> counts = candidates
 .GroupJoin(
   list1,
   c => c,
   s => s,
   (c, g) => new { Key = c, Count = g.Count()
 )
 .ToDictionary(x => x.Key, x => x.Count);

List<string> missing = counts.Keys
  .Where(key => counts[key] == 0)
  .ToList();

List<string> tooMany = counts.Keys
  .Where(key => 1 < counts[key])
  .ToList();

答案 4 :(得分:0)

    private bool ContainsAllCandidatesOnce(List<String> list1)
    {
        return list1.Where(s => candidates.Contains(s)).Count() == candidates.Count();
    }

    private IEnumerable<String> MissingCandidates(List<String> list1) 
    {
        return candidates.Where(s => list1.Count(c => c == s) != 1);
    } 

答案 5 :(得分:0)

如何使用HashSet而不是List?

答案 6 :(得分:-1)

private static bool ContainsAllCandidatesOnce(List<string> lotsOfCandidates)
{
    foreach (string candidate in allCandidates)
    {
        if (lotsOfCandidates.Count(t => t.Equals(candidate)) != 1)
        {
            return false;
        }
    }

    return true;
}

private static IEnumerable<string> MissingCandidates(List<string> lotsOfCandidates)
{
    List<string> missingCandidates = new List<string>();

    foreach (string candidate in allCandidates)
    {
        if (lotsOfCandidates.Count(t => t.Equals(candidate)) != 1)
        {
            missingCandidates.Add(candidate);
        }
    }

    return missingCandidates;
}