Як підрахувати дублікати у списку за допомогою LINQ


77

У мене є список предметів

  • John ID
  • Ідентифікатор Метта
  • John ID
  • Скотт ідентифікатор
  • Ідентифікатор Метта
  • John ID
  • Ідентифікатор Лукаса

Я хочу повернути їх назад у такий список, що також означає, що я хочу сортувати за найбільшою кількістю дублікатів.

  • John ID 3
  • Мат ID 2
  • Скотт Ідентифікатор 1
  • Ідентифікатор Лукаса 1

Повідомте мене, як я можу це зробити за допомогою LINQ та C #.

Дякую всім

EDIT 2 Показаний код:

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

Цей запит відображає такі результати:

  • 1 привіт світовий час
  • 1 привіт світовий час
  • 1 Привіт Світ.
  • 1 привіт світовий час
  • 1 привіт світовий час
  • 1 привіт світовий час
  • 1 Привіт Світ.
  • 1 привіт світовий час

Це дає мені підрахунок і ім’я, але це не дає мені ідентифікатор гри ....

Він повинен відображати:

  • 6 привіт світових часів 234234
  • 2 Привіт Світ. 23432432

з огляду на ваші результати очевидно, що програма трактує всі ваші елементи як різні - як я вже говорив, вам потрібно застосувати спеціальний порівняльник, інакше неможливо вибрати різні значення
aku

Відповіді:


107

Ви можете використовувати "групувати за" + "за замовленням". Див LINQ 101 для деталей

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

У відповідь на цю публікацію (тепер видалено):

Якщо у вас є список деяких користувацьких об'єктів, вам потрібно використовувати спеціальний порівняльник або групувати за певними властивостями.

Також запит не може відображати результат. Покажіть нам повний код, щоб отримати кращу допомогу.

На основі вашого останнього оновлення:

У вас є такий рядок коду:

group xx by xx into g

Оскільки xx - це спеціальний об'єкт, система не знає, як порівнювати один елемент з іншим. Як я вже писав, вам потрібно керувати компілятором та надати деяку властивість, яка буде використана для порівняння об'єктів, або надати власний порівняльник. Ось приклад:

Зверніть увагу, що я використовую Foo.Name як ключ - тобто об'єкти будуть згруповані на основі значення Name .

Є одна фішка - ви розглядаєте 2 об’єкти як дублікати на основі їх назв, але як щодо Id? У моєму прикладі я просто беру Id першого об'єкта в групі. Якщо ваші об'єкти мають різні ідентифікатори, це може бути проблемою.

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

Готово, тепер ви можете побачити, на що я дивлюсь.
SpoiledTechie.com

виберіть новий {Ім'я = g.Key, Count = count, ID = g.First (). ID}; Це була лінія, яка змусила його працювати. Дякую Аку. Це перша частина .ID, яка змусила його працювати. Ур блискучий ...
SpoiledTechie.com

Дякую за x.First().IDсправу
ParPar

50

Трохи коротша версія з використанням ланцюжка методів:

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

Простота та досвід.
Hitsa

9

Ви також можете зробити словник:

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

6

Інші рішення використовують GroupBy. GroupByє повільним (він зберігає всі елементи в пам'яті), тому я написав власний метод 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;
}

0

Ось повна програма, будь ласка, перевірте це

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();
}        
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.