web-dev-qa-db-fra.com

Comment compter les doublons dans la liste avec LINQ

J'ai une liste d'articles

  • John ID
  • Matt ID
  • John ID
  • Scott ID
  • Matt ID
  • John ID
  • Lucas ID

Je veux les replacer dans une liste comme celle-ci, ce qui signifie également que je veux trier selon le nombre le plus élevé de doublons.

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

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

Merci a tous

EDIT 2 Affichage du 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 ces résultats:

  • 1 Bonjour tout le monde
  • 1 Bonjour tout le monde
  • 1 Bonjour tout le monde.
  • 1 Bonjour tout le monde
  • 1 Bonjour tout le monde
  • 1 Bonjour tout le monde
  • 1 Bonjour tout le monde.
  • 1 Bonjour tout le monde

Cela me donne le compte et le nom, mais cela ne me donne pas l'ID du jeu ....

Il devrait afficher:

  • 6 bonjour monde fois 234234
  • 2 Bonjour tout le monde. 23432432
66
SpoiledTechie.com

Vous pouvez utiliser "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 à cet article (maintenant supprimé):

Si vous avez une liste d'objets personnalisés, vous devez utiliser comparateur personnalisé ou groupe par propriété spécifique.

De plus, la requête ne peut pas afficher le résultat. Montrez-nous le 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

Comme xx est un système d'objet personnalisé, le système ne sait pas comment comparer un élément à un autre . Comme je l'ai déjà écrit, vous devez guider le compilateur et fournir une propriété qui sera utilisée dans la comparaison d'objets ou un comparateur personnalisé. Voici un exemple:

Notez que j’utilise Foo.Name comme clé - c’est-à-dire que les objets seront regroupés en fonction de la valeur de la propriété Name.

Il y a un problème: vous traitez 2 objets à dupliquer en fonction de leur nom, mais qu'en est-il de l'id? Dans mon exemple, je prends juste l'ID du premier objet d'un groupe. Si vos objets ont des identifiants différents, cela peut poser 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);
}
92
aku

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);
}
42
CMS

Vous pouvez aussi faire un dictionnaire:

 var list = new List<string> { "a", "b", "a", "c", "a", "b" };
 var result = list.GroupBy(x => x)
            .ToDictionary(y=>y.Key, y=>y.Count())
            .OrderByDescending(z => z.Value);

 foreach (var x in result)
        {
            Console.WriteLine("Value: " + x.Key + " Count: " + x.Value);
        }
7
Willy David Jr

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;
}
4
Colonel Panic

Voici le programme complet s'il vous plaît vérifier ceci

static void Main(string[] args)
{
    List<string> li = new List<string>();
    li.Add("Ram");
    li.Add("shyam");
    li.Add("Ram");
    li.Add("Kumar");
    li.Add("Kumar");

    var x = from obj in li group obj by obj into g select new { Name = g.Key, Duplicatecount = g.Count() };
    foreach(var m in x)
    {
        Console.WriteLine(m.Name + "--" + m.Duplicatecount);
    }
    Console.ReadLine();
}        
0
Debendra Dash