为什么使用Distinct函数时需要应用Except函数?

3

可能是重复问题:
Except与Distinct有类似效果吗?

我有两个类似于List<String>的列表

lstOne = { "A", "B", "C" ,"C" ,"C" };
lstTwo = { "A" };

lstResult = lstOne.Except(lstTwo).ToList();

现在期望的输出结果是:
lstReult = { "B","C","C","C" };

但实际结果是这样的:
lstResult = { "B","C" };

为什么会这样?我使用了Except,为什么还要应用Distinct
3个回答

12

"Except" 被记录为返回两个序列的集合差异。

根据定义,集合差异是一个集合。按照定义,集合不包含重复项。

期望输出结果是...

不,期望输出结果和实际输出结果相同。

如果您期望得到不同的结果,建议您将期望值调整为与文档记录的行为相匹配。


我第一次遇到这种行为时感到相当惊讶。也许这个方法的命名可以更好些。 - CodesInChaos
2
理解“集合差异”需要足够的数学背景,以了解集合不包含重复元素。浏览文档时,很容易忽略它在谈论集合而不是序列。我会明确指出它返回不同的元素,比如指定“返回第一个序列中所有不属于第二个序列的不同元素”。 - CodesInChaos
@CodeInChaos:说得好。下次我见到文档经理时会向他提及这一点。 - Eric Lippert

11

这被记录为返回“包含两个序列之间元素的差异集合的序列”。集合不包含重复项。

这也许是一个微妙的点,但它按照规范起作用。

如果你想要重复项:

var lstOne = new[] { "A", "B", "C" ,"C" ,"C" };
var except = new HashSet<string> { "A" };

var lstResult = lstOne.Where(x => !except.Contains(x)).ToList();
   // ^^ "B", "C", "C", "C"

使用HashSet可以去除重复项。如果你要检查的是 { "C", "C" },那你会怎么处理? - Mike Loux
@Mike 首先,你需要明确你所说的 { "C", "C" } 的含义 - 从集合论的角度来看,这与 { "C" } 是相同的。如果你的意思是“两个 "C" 实例”,那么你需要定义你是否指相邻的(即有序序列),还是只是计数方式上的区别。 - Marc Gravell
不确定是邻接还是计数或其他什么。然而,我有一个需求,使用上面的例子,第一个列表为{"A", "B", "C", "C", "C"},并移除{"C", "C"},我需要留下{"A", "B", "C"}。使用HashSet作为第二个列表将使我得到{"A", "B", "C", "C"}。而且,更复杂的是,我需要对复杂类型执行此操作,而不是字符串。希望这能更好地解释问题。 - Mike Loux

2

MSDN定义:“使用默认的相等比较器来比较值,通过生成两个序列的差集来产生集合的差异。” --> 差异作为集合 --> 每个键都是唯一的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接