使用LINQ去除任何重复的值

6

我在SO上看到了这个问题,但它没有回答我的问题,因为我想要删除所有重复值的实例。

例如,如果我有一个包含以下值的列表:A,A,C,D,B,A,E,E

我想编写一些逻辑,使新列表具有这些值:C,D,B。

由于A和E被视为重复项,我希望完全删除它们。

因此,考虑到这一点,这是我的代码:

// List having duplicate string elements.
List<string> list = new List<string>();
list.Add("A");
list.Add("A");
list.Add("C");
list.Add("D");
list.Add("B");
list.Add("A");
list.Add("E");
list.Add("E");

// Get distinct elements.
var distinct = (from item in list orderby item select item).Distinct();

foreach (string value in distinct)
{
    Console.WriteLine("Distinct : {0}", value);
}

这是输出结果:

A、B、C、D、E


@GrantWinney 是的 - 谢谢,我刚意识到! - geedubb
1
修改了我的问题,因为你们有点过于追求细节 :( - nick gowdy
7个回答

9
这应该可以解决问题(C 应该在列表中,代码示例中只出现了一次)。
var distinct = list.GroupBy(x=>x).Where(y=>y.Count()==1).Select(z=>z.Key);

2
没错,但你应该使用 Select 子句来选择实际的值;否则,distinct 将是一系列的 IGrouping - sloth
@DominicKexel 抱歉如果这听起来像个愚蠢的问题。为什么要在查询中添加SELECT?我本来要将其标记为正确,但看到了你的评论。我使用了CeeTee的代码,然后两次都添加了select子句,当它达到我的断点时看起来是一样的。 - nick gowdy
选择语句使查询返回一个IEnumerable<string> - 如果没有它,返回类型将是IEnumerable<IGrouping<string, string>>。我根据@DominicKexel的评论更新了我的答案。 - Original10
1
这个答案是正确的。问题在于GroupBy返回一个IGrouping序列,表示按字母分组的组,每个组的键是该组的字母,每个组包含其字母的所有出现次数,例如[A->A,A,A],[B->B]等。然后这些组被过滤,但你只对每个组的键感兴趣,而不是组本身。 - sloth
@DominicKexel 好的,我想我明白了。谢谢你的解释 :) - nick gowdy
如果性能很重要,您可以使用(y=>!y.Skip(1).Any())来避免迭代整个大组。 - Andrew Coonce

4
那么这将只返回非重复项:
var filtered = list.Where(item => list.Count(x => x == item) < 2);

1
这是正确的。而且它比选择的答案更有效率吗? - geedubb
2
@geedubb 这种方法效率显然较低。它需要迭代整个列表N+1次,而被接受的答案只需要迭代一次。 - Servy
1
如果你有一个大数据集,这种方法的效率会低很多。但对于一个小列表来说,我可能会使用它,因为它更直观易懂。 - Kjartan

1
你可以按每个字母分组,然后获取只出现一次的那些。
var singleInstances = list.GroupBy(x => x)
                          .Where(x => x.Count() == 1)
                          .Select(x => x.Key)
                          .ToList();

输出:

C
D
B

1

试试这个

var duplicates = list.GroupBy(x => x)
                         .Where(g => g.Count() == 1)
                         .Select(g => g.Key)
                         .ToList();

那会返回所有重复项。

1
应该是 == 1,而不是 > 1 - sloth
是的 - 这样更好 ;) - geedubb
Hehe匆忙写的! - Matt W

1
你可以将项目分组,然后从每个只有一个项目的组中选择一个项目:
var filteredList = list.GroupBy(x => x).Where(grp => grp.Count() == 1).Select(grp => grp.Key);

0
   List<string> list = new List<string>();
                            list.Add("A");
                            list.Add("A");
                            list.Add("C");
                            list.Add("D");
                            list.Add("B");
                            list.Add("A");
                            list.Add("E");
                            list.Add("E");

            var distinct = from item in list
                           group item by item into x
                           where x.Count().Equals(1)
                           select x;

0
List<string> list = new List<string>();
                        list.Add("A");
                        list.Add("A");
                        list.Add("C");
                        list.Add("D");
                        list.Add("B");
                        list.Add("A");
                        list.Add("E");
                        list.Add("E");

var query = list.Except(list.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key));

为什么要做额外的工作,而不是像其他答案一样从一开始就过滤掉组数为1的组? - Servy

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