87 votes

Comment compter les doublons dans la liste avec LINQ

J'ai une liste d'éléments

  • Jean-ID
  • Matt ID
  • Jean-ID
  • Scott ID
  • Matt ID
  • Jean-ID
  • Lucas ID

Je veux les pousser en arrière dans une liste comme si ce qui signifie aussi je veux trier par le plus grand nombre de doublons.

  • John ID 3
  • Matt ID 2
  • Scott ID 1
  • Lucas ID 1

Laissez-moi savoir comment je peux faire cela avec LINQ et C#.

Merci À Tous

EDIT 2 Montrant Code:

    List<game> inventory = new List<game>();
    drinkingforDataContext db = new drinkingforDataContext();
    foreach (string item in tbTitle.Text.Split(' '))
    {

        List<game> getItems = (from dfg in db.drinkingfor_Games
                               where dfg.game_Name.Contains(tbTitle.Text)
                               select new game
                               {
                                   gameName = dfg.game_Name,
                                   gameID = Boomers.Utilities.Guids.Encoder.EncodeURLs(dfg.uid)
                               }).ToList<game>();

        for (int i = 0; i < getItems.Count(); i++)
        {
            inventory.Add(getItems[i]);
        }
    }

    var items = (from xx in inventory
                 group xx by xx into g
                 let count = g.Count()
                 orderby count descending
                 select new
                    {
                        Count = count,
                        gameName = g.Key.gameName,
                        gameID = g.Key.gameID
                    });

    lvRelatedGames.DataSource = items;
    lvRelatedGames.DataBind();

Cette requête affiche les résultats suivants:

  • 1 bonjour tout le monde des fois
  • 1 bonjour tout le monde des fois
  • 1 Bonjour Tout Le Monde.
  • 1 bonjour tout le monde des fois
  • 1 bonjour tout le monde des fois
  • 1 bonjour tout le monde des fois
  • 1 Bonjour Tout Le Monde.
  • 1 bonjour tout le monde des fois

Il me donne le nombre et le nom, mais il ne veut pas me donner l'ID du jeu....

Il doit afficher:

  • 6 bonjour tout le monde, fois 234234
  • 2 Bonjour Tout Le Monde. 23432432

115voto

aku Points 54867

Vous pouvez utiliser le bouton "group by" + "orderby". Voir LINQ 101 pour plus de détails

var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = from x in list
        group x by x into g
        let count = g.Count()
        orderby count descending
        select new {Value = g.Key, Count = count};
foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}

En réponse à ce post (maintenant supprimé):

Si vous avez une liste de certains des objets personnalisés, alors vous devez utiliser personnalisée comparer ou d'un groupe spécifique de la propriété.

Également de la requête ne peut pas afficher le résultat. Montrez-nous code complet pour obtenir une meilleure aide.

Basé sur votre dernière mise à jour:

Vous avez cette ligne de code:

group xx by xx into g

Depuis xx est un objet personnalisé système ne sais pas comment comparer un article contre un autre. Comme je l'ai déjà écrit, vous avez besoin de guide compilateur et de fournir des biens qui seront utilisés dans les objets de comparaison ou de fournir des comparer. Voici un exemple:

Notez que j'utilise Foo.Nom comme un touche - à-d. les objets seront regroupés en fonction de la valeur du Nom de la propriété.

Il y a un hic - vous traiter les 2 objets en double en fonction de leurs noms, mais qu'en est Id ? Dans mon exemple, je viens de prendre l'Id de l'objet premier d'un groupe. Si vos objets différents Ids, il peut être un problème.

//Using extension methods
var q = list.GroupBy(x => x.Name)
            .Select(x => new {Count = x.Count(), 
                              Name = x.Key, 
                              ID = x.First().ID})
            .OrderByDescending(x => x.Count);

//Using LINQ
var q = from x in list
        group x by x.Name into g
        let count = g.Count()
        orderby count descending
        select new {Name = g.Key, Count = count, ID = g.First().ID};

foreach (var x in q)
{
    Console.WriteLine("Count: " + x.Count + " Name: " + x.Name + " ID: " + x.ID);
}

65voto

CMS Points 315406

Version légèrement plus courte en utilisant la chaîne de méthodes:

 var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = list.GroupBy(x => x)
            .Select(g => new {Value = g.Key, Count = g.Count()})
            .OrderByDescending(x=>x.Count);

foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}
 

8voto

Colonel Panic Points 18390

Les autres solutions utilisent GroupBy . GroupBy est lent (il contient tous les éléments en mémoire) alors j'ai écrit ma propre méthode CountBy :

 public static Dictionary<TKey,int> CountBy<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
    var countsByKey = new Dictionary<TKey,int>();
    foreach(var x in source)
    {
        var key = keySelector(x);
        if (!countsByKey.ContainsKey(key))
            countsByKey[key] = 0;
        countsByKey[key] += 1;
    }
    return countsByKey;
}
 

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