如何使用LINQ从列表中获取重复项?

Tho*_*eld 168 c# linq duplicates

我有一个List<string>喜欢:

List<String> list = new List<String>{"6","1","2","4","6","5","1"};
Run Code Online (Sandbox Code Playgroud)

我需要将列表中的重复项目放入新列表中.现在我正在使用嵌套for循环来执行此操作.

结果list将包含{"6","1"}.

是否有任何想法使用LINQlambda表达式

Lee*_*Lee 237

var duplicates = lst.GroupBy(s => s)
    .SelectMany(grp => grp.Skip(1));
Run Code Online (Sandbox Code Playgroud)

请注意,这将返回所有重复项,因此,如果您只想知道源列表中哪些项重复,则可以应用于Distinct生成的序列或使用Mark Byers提供的解决方案.

  • lst.GroupBy(s => s.ToUpper()).SelectMany(grp => grp.Skip(1)); 如果你想做一个不区分大小写的比较:) (5认同)
  • @JohnJB - 有一个'GroupBy`的重载,它允许你提供一个`IEqualityComparer`,而不是使用`ToUpper`来进行不区分大小写的比较. (2认同)
  • @ParPar - [这个答案](http://stackoverflow.com/a/19817834/152602)做你想做的事吗? (2认同)
  • 正如@ScottLangham指出的那样,它实际上并不会返回所有重复的记录,它会返回每个组中第一次出现的所有重复记录。所以是的,如果您只列出了唯一的重复值,则可以使用Distinct方法来解决此问题,但是如果您希望所有重复的行都可以,那么我发现Scott的答案就是可以解决的方法。 (2认同)

Mar*_*ers 171

这是一种方法:

List<String> duplicates = lst.GroupBy(x => x)
                             .Where(g => g.Count() > 1)
                             .Select(g => g.Key)
                             .ToList();
Run Code Online (Sandbox Code Playgroud)

GroupBy元素组合在一起,并Where筛选出仅出现一次的元素,只留下重复的元素.


Luk*_*keH 37

这是另一种选择:

var list = new List<string> { "6", "1", "2", "4", "6", "5", "1" };

var set = new HashSet<string>();
var duplicates = list.Where(x => !set.Add(x));
Run Code Online (Sandbox Code Playgroud)

  • Downvote不是来自,但我真的应该避免使用'.Where`中的副作用,所以这可能是原因. (5认同)
  • 哈哈,+1创新:)不仅如此,这确实提供了OP想要的东西.这里的问题是,如果第二次枚举查询,它可以给出错误答案(为了防止,您必须清除集合或每次初始化一个新集合). (2认同)

Sco*_*ham 24

我知道这不是原始问题的答案,但你可能会发现自己遇到了这个问题.

如果您想要结果中的所有重复项,则以下方法有效.

var duplicates = list
    .GroupBy( x => x )               // group matching items
    .Where( g => g.Skip(1).Any() )   // where the group contains more than one item
    .SelectMany( g => g );           // re-expand the groups with more than one item
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我需要所有重复项,以便我可以在UI中将它们标记为错误.


Mic*_*ael 18

我根据@ Lee对OP的回应编写了这个扩展方法. 注意,使用了默认参数(需要C#4.0).但是,在C#3.0中重载方法调用就足够了.

/// <summary>
/// Method that returns all the duplicates (distinct) in the collection.
/// </summary>
/// <typeparam name="T">The type of the collection.</typeparam>
/// <param name="source">The source collection to detect for duplicates</param>
/// <param name="distinct">Specify <b>true</b> to only return distinct elements.</param>
/// <returns>A distinct list of duplicates found in the source collection.</returns>
/// <remarks>This is an extension method to IEnumerable&lt;T&gt;</remarks>
public static IEnumerable<T> Duplicates<T>
         (this IEnumerable<T> source, bool distinct = true)
{
     if (source == null)
     {
        throw new ArgumentNullException("source");
     }

     // select the elements that are repeated
     IEnumerable<T> result = source.GroupBy(a => a).SelectMany(a => a.Skip(1));

     // distinct?
     if (distinct == true)
     {
        // deferred execution helps us here
        result = result.Distinct();
     }

     return result;
}
Run Code Online (Sandbox Code Playgroud)


Tha*_*kur 10

希望这会有所帮助

int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 };

var duplicates = listOfItems 
    .GroupBy(i => i)
    .Where(g => g.Count() > 1)
    .Select(g => g.Key);

foreach (var d in duplicates)
    Console.WriteLine(d);
Run Code Online (Sandbox Code Playgroud)


exp*_*rer 10

  List<String> list = new List<String> { "6", "1", "2", "4", "6", "5", "1" };

    var q = from s in list
            group s by s into g
            where g.Count() > 1
            select g.First();

    foreach (var item in q)
    {
        Console.WriteLine(item);

    }
Run Code Online (Sandbox Code Playgroud)