如何保证列表包含序列中的每个字符串恰好一次
问题描述:
假设我有一个字符串列表,像这样:如何保证列表<String>包含序列中的每个字符串恰好一次
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)
{
????
}
顺序无关紧要。
答
这可能不是在速度方面最优的,但两者的查询足够短,以适应在一行,并很容易理解:
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);
}
答
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);
}
答
这应该是相当有效率:
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();
- 筛选出重复。
- 确保所有候选项都发生在过滤出的集合中。
答
这里我们说的是Except,Intersect和Distinct。我可以使用带表达式的lamba运算符,但它必须遍历每个项目。该功能可用于预定义的功能。
你的第一个方法
var candidates = new List<String> { "Peter", "Chris", "Maggie", "Virginia" };
private bool ContainsAllCandidatesOnce(List<String> list1)
{
list1.Intersect(candidates).Distinct().Any();
}
这将使从列表1这是常见的候选列表中的任何元素,也可以为你的第二个做到这一点的其他方式
candidates.Intersect(list1).Distinct().Any();
方法
private IEnumerable<String> MissingCandidates(List<String> list1)
{
list1.Except(candidates).AsEnumerable();
}
这将从列表1中删除候选中的所有元素。如果你想要它可以做的另一种方式
candidates.Except(list1).AsEnumerable();
答
GroupJoin是工作的正确工具。从msdn:
群组加入产生分层的结果,这意味着元件 从外与来自 内匹配元素的集合配对。 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();
答
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;
}
看到了这个问题:http://*.com/questions/568347/how-do-i-use-linq-to-obtain-a-unique-list-of-properties-from -a-list-of-objects –
对于这些类型或问题,请提供问题和答案,以便您提出的问题以及所得到的内容变得清晰,如果list1为“新”,那么这两个方法将返回什么。列表 {“foo” ,“酒吧”}'我想'新列表 {“酒吧”,“富”}'。 –