Подсчет вхождений числа в массив C#

У меня есть массив moviesRented, в котором хранятся следующие значения: 17 3 3 2 2 2 1 1 1 1. Значения были прочитаны из проанализированных данных в текстовом файле.

Мне нужно распечатать количество каждого значения. Например, вывод должен быть:
4 появления из 1
3 появления из 2
2 появления из 3
1 появление из 17

Вот мой текущий код:

            StreamReader inFile = new StreamReader("project-files/transactions.txt");
            string line = inFile.ReadLine();

            while(line != null){

                string[] temp = line.Split("#");
            
                moviesRented[count] = int.Parse(temp[2]);                
                count++;

                line = inFile.ReadLine();
            }

            inFile.Close();

            for(int i = 0; i < count - 1; i++){
                for(int j = i + 1; j < count; j++){

                    if (moviesRented[i] < moviesRented[j]){
                        int temp = moviesRented[i];
                        moviesRented[i] = moviesRented[j];
                        moviesRented[j] = temp;
                    }
                }
            }

            // output sorted array
            for(int i = 0; i < count; i++){
                Console.WriteLine(moviesRented[i]);
            }

Я могу получить необходимые значения из текстового файла (они хранятся в массиве moviesRented), а также отсортировать их от большего к меньшему.

Вот результат moviesRented после сортировки:
17
3
3
2
2
2
1
1
1
1

Как мне подсчитать значения? Я попробовал что-то вроде этого:

        StreamReader inFile = new StreamReader("project-files/transactions.txt");
        string line = inFile.ReadLine();

        while(line != null){

            string[] temp = line.Split("#");
        
            moviesRented[count] = int.Parse(temp[2]);                
            count++;

            line = inFile.ReadLine();
        }

        inFile.Close();

        for(int i = 0; i < count - 1; i++){

            int tempCount = 0;
            for(int j = i + 1; j < count; j++){

                if (moviesRented[i] < moviesRented[j]){
                    int temp = moviesRented[i];
                    moviesRented[i] = moviesRented[j];
                    moviesRented[j] = temp;
                }

                // this is new compared to the code above
                // it compares iteration with next iteration
                // and if they match then add 1 to tempCount
                if (moviesRented[i] == moviesRented[j]){
                    tempCount++;
                }
            }
            Console.WriteLine($"{moviesRented[i]} {tempCount}");
        }

Это считается, но экземпляров каждого значения слишком много — вот результат с приведенным выше кодом:
17 1
3 1
3 2
2 2
2 1
2 3
1 3
1 2
1 1

Но мне нужно САМОЕ ВЫСОКОЕ значение вхождения каждого слова, а не все, как в приведенном выше выводе.

Как бы я отобразил (вывел на консоль) каждое значение moviesRented и сколько раз оно встречается в порядке убывания, например, как первый вывод, упомянутый выше:
4 появления из 1
3 появления из 2
2 появления из 3
1 появление из 17

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
82
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Самый простой способ — использовать LINQ:

var statistics = from x in moviesRented
                 group x by x into g
                 select new { Number = g.Key, Count = g.Count() };

foreach(var statItem in statistics)
   Console.WriteLine($"{statItem.Count} occurence(s) of {statItem.Number}");

Известный классический алгоритм заключается в использовании словаря (хеш-таблицы), который содержит увеличенное количество каждого значения.

Это очень помогло!

john jacobs 15.04.2024 22:49

Вы можете сделать это, просто используя Linq:

int[] moviesRented = [17, 3, 3, 2, 2, 2, 1, 1, 1, 1];
        
var counts = new Dictionary<int, int>();
foreach(var item in moviesRented)
{
    // Count the occurences
    var count = moviesRented.Count(i => i == item);
    counts[item] = count;
}
        
// Order by occurences
var ordered = counts.OrderByDescending(v => v.Value);
foreach(var item in ordered)
{
    Console.WriteLine($"{item.Value} occurrence of {item.Key}");
}

Выход:

4 occurrence of 1
3 occurrence of 2
2 occurrence of 3
1 occurrence of 17

Рабочий пример можно найти здесь

Сортировка по наиболее встречающимся...

   int[] moviesRented = [17, 3, 3, 2, 2, 2, 1, 1, 1, 1];
   IEnumerable<(int key, int count)> counts = moviesRented
       .GroupBy(i => i, (key, items) => (key, items.Count()));

    foreach (var tpl in counts.OrderByDescending(t => t.count))
        Console.WriteLine("{0} occurences(s) of {1}", tpl.count, tpl.key);

Вот еще один вариант LINQ.

  • Фильмы сгруппированы по разным ценностям.
  • Преобразован в словарь, где отдельные фильмы являются ключами, а соответствующие счетчики — значениями.
  • Числа отсортированы по убыванию

.

int[] moviesRented = { 17, 3, 3, 2, 2, 2, 1, 1, 1, 1 };

var counts = moviesRented.GroupBy(i => i)
                         .ToDictionary(g => g.Key, g =>g.Count())
                         .OrderByDescending(kv => kv.Value);

foreach (var item in counts)
{
  Console.WriteLine($"{item.Value} occurrence(s) of {item.Key}");
}

Другие вопросы по теме