180 votes

Comment obtenir des éléments en double d'une liste à l'aide de LINQ?

J'ai un List<string> comme:

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

Je dois placer les éléments en double dans la liste dans une nouvelle liste. Maintenant, j'utilise la boucle nested for pour ce faire.

Le list résultant contiendra {"6","1"}

Y a-t-il une idée de faire cela en utilisant l'expression LINQ ou Lambda?

250voto

Lee Points 63849
 var duplicates = lst.GroupBy(s => s)
    .SelectMany(grp => grp.Skip(1));
 

Notez que cela renverra tous les doublons, donc si vous voulez seulement savoir quels éléments sont dupliqués dans la liste source, vous pouvez appliquer Distinct à la séquence résultante ou utiliser la solution donnée par Mark Byers.

181voto

Mark Byers Points 318575

Voici une façon de le faire:

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

Les groupes GroupBy regroupent les éléments identiques, tandis que les Where filtrent ceux qui n'apparaissent qu'une seule fois, vous laissant uniquement les doublons.

38voto

LukeH Points 110965

Voici une autre option:

 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));
 

27voto

Scott Langham Points 17447

Je sais que ce n'est pas la réponse à la question initiale, mais vous pouvez vous retrouver ici avec ce problème.

Si vous voulez tous les éléments en double dans vos résultats, procédez comme suit.

 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
 

Dans ma situation, j'ai besoin de tous les doublons pour pouvoir les marquer dans l'interface utilisateur comme des erreurs.

19voto

Michael Points 1649

J'ai écrit cette méthode d'extension basée sur la réponse de @ Lee à l'OP. Notez qu'un paramètre par défaut a été utilisé (nécessitant C # 4.0). Cependant, un appel de méthode surchargé en C # 3.0 suffirait.

 /// <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;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X