2015-06-16 3 views
0

Как я могу найти режим списка чисел? Я знаю логику этого (я думаю), но я не знаю, как реализовать эту логику или преобразовать то, что мой мозг думает о работоспособном коде.Режим поиска в списке целых чисел

Это то, что я знаю:

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

+0

ли это домашнее задание? Если да, существуют ли ограничения в отношении того, какие методы библиотеки вы можете использовать? – phoog

ответ

1

Да, вы правы:

Пусть мы имеемсписок из номера:

List<int> myValues = new List<int>(new int[] { 1, 3, 3, 3, 7, 7 }); 

Вы должны иметь цикл, который проходит через список один раз :

foreach (var val in myValues) 
{ 
} 

посмотреть, сколько раз число повторяется в массиве, чтобы сохранить время число повторяется:

Dictionary<int, int> repetitions = new Dictionary<int, int>(); 
foreach (var val in myValues) 
{ 
    if (repetitions.ContainsKey(val)) 
     repetitions[val]++; // Met it one more time 
    else 
     repetitions.Add(val, 1); // Met it once, because it is not in dict. 
} 

Теперь ваш словарь repetitions хранит сколько (точно значение) раз повторенные ключ значение ,
Затем вам нужно найти запись режима (т. Е. Запись с наивысшим временем повторений (т. Е. Наивысшее значение)) и взять ее. LINQ поможет нам - давайте отсортируем массив по значению и возьмем последний ... или отсортируем его по убыванию и возьмем первый. Фактически, это то же самое с точки зрения результата и производительности.

var modeRecord = repetitions.OrderByDescending(x => x.Value).First(); 
// or 
var modeRecord = repetitions.OrderBy(x => x.Value).Last(); 

Вот оно! Здесь у нас есть режим:

List<int> myValues = new List<int>(new int[] { 1, 3, 3, 3, 7, 7 }); 
Dictionary<int, int> repetitions = new Dictionary<int, int>(); 

foreach (var val in myValues) 
{ 
    if (repetitions.ContainsKey(val)) 
     repetitions[val]++; // Met it one more time 
    else 
     repetitions.Add(val, 1); // Met it once, because it is not in dict. 
} 

var modeRecord = repetitions.OrderByDescending(x => x.Value).First(); 

Console.WriteLine("Mode is {0}. It meets {1} times in an list", modeRecord.Key, modeRecord.Value); 

Ваша логика расчета режима хороша. Все, что вам нужно, это следующее собственные инструкции в коде :)

+0

Хороший ответ. Более подробный, но более эффективный (меньше ключевых запросов): 'int count; if (repetitions.TryGetValue (val, out count)) повторения [val] = count + 1; else повторения [val] = 1; ' – phoog

3

A LinQ подход, более краткая, но почти наверняка менее эффективны, чем Yeldar Курмангалиев-х:

int FindMode(IEnumerable<int> data) 
{ 
    return data 
     .GroupBy(n => n) 
     .Select(x => new { x.Key, Count = x.Count() }) 
     .OrderByDescending(a => a.Count) 
     .First() 
     .Key; 
} 

Это не обрабатывает случай, когда data пуст, ни там, где в наборе данных есть две или более точек данных с одинаковой частотой.

0

Вот альтернативный подход LINQ:

var values = new int[] { 1, 3, 3, 3, 7, 7 }; 

var mode = 
    values 
     .Aggregate(
      new { best = 0, best_length = 0, current = 0, current_length = 0 }, 
      (a, n) => 
      { 
       var current_length = 1 + (a.current == n ? a.current_length : 0); 
       var is_longer = current_length > a.best_length; 
       return new 
       { 
        best = is_longer ? n : a.best, 
        best_length = is_longer ? current_length : a.best_length, 
        current = n, 
        current_length, 
       }; 
      }).best; 
Смежные вопросы