Подтвердить что ты не робот

Найти наиболее встречающееся число в списке <int>

Есть ли быстрый и приятный способ использования linq?

4b9b3361

Ответ 1

Как насчет:

var most = list.GroupBy(i=>i).OrderByDescending(grp=>grp.Count())
      .Select(grp=>grp.Key).First();

или в синтаксисе запроса:

var most = (from i in list
            group i by i into grp
            orderby grp.Count() descending
            select grp.Key).First();

Конечно, если вы будете использовать это повторно, вы можете добавить метод расширения:

public static T MostCommon<T>(this IEnumerable<T> list)
{
    return ... // previous code
}

Затем вы можете использовать:

var most = list.MostCommon();

Ответ 2

Не уверен в лямбда-выражениях, но я бы

  • Сортировка списка [O (n log n)]

  • Сканировать список [O (n)] на поиск самой длинной длины.

  • Повторно сканировать [O (n)], сообщая каждому номеру, имеющему эту длину.

Это потому, что может быть более одного наиболее часто встречающегося числа.

Ответ 3

Из моего ответа здесь:

public static IEnumerable<T> Mode<T>(this IEnumerable<T> input)
{            
    var dict = input.ToLookup(x => x);
    if (dict.Count == 0)
        return Enumerable.Empty<T>();
    var maxCount = dict.Max(x => x.Count());
    return dict.Where(x => x.Count() == maxCount).Select(x => x.Key);
}

var modes = { }.Mode().ToArray(); //returns { }
var modes = { 1, 2, 3 }.Mode().ToArray(); //returns { 1, 2, 3 }
var modes = { 1, 1, 2, 3 }.Mode().ToArray(); //returns { 1 }
var modes = { 1, 2, 3, 1, 2 }.Mode().ToArray(); //returns { 1, 2 }

Я пошел на тест производительности между вышеприведенным подходом и .

source = {}, итерации = 1000000
шахта - 300 мс, Дэвид - 930 мс

source = {1}, итерации = 1000000
 шахта - 1070 мс, Давид - 1560 мс

source = 100+ ints с двумя дубликатами, итерациями = 10000
   мой - 300 мс, Дэвид - 500 мс

source = 10000 случайных чисел с примерно 100+ дубликатами, итераций = 1000
шахта - 1280 мс, Дэвид - 1400 мс

Ответ 4

Вот еще один ответ, который кажется быстрым. Я думаю, ответ Nawfal, как правило, быстрее, но это может затенять его на длинные последовательности.

public static IEnumerable<T> Mode<T>(
    this IEnumerable<T> source,
    IEqualityComparer<T> comparer = null)
{
    var counts = source.GroupBy(t => t, comparer)
        .Select(g => new { g.Key, Count = g.Count() })
        .ToList();

    if (counts.Count == 0)
    {
        return Enumerable.Empty<T>();
    }

    var maxes = new List<int>(5);
    int maxCount = 1;

    for (var i = 0; i < counts.Count; i++)
    {
        if (counts[i].Count < maxCount)
        {
            continue;
        }

        if (counts[i].Count > maxCount)
        {
            maxes.Clear();
            maxCount = counts[i].Count;
        }

        maxes.Add(i);
    }

    return maxes.Select(i => counts[i].Key);
}

Ответ 5

Кто-то попросил решение, где есть связи. Вот удар по этому поводу:

int indicator = 0

var result =
  list.GroupBy(i => i)
    .Select(g => new {i = g.Key, count = g.Count()}
    .OrderByDescending(x => x.count)
    .TakeWhile(x =>
    {
      if (x.count == indicator || indicator == 0)
      {
        indicator = x.count;
        return true;
      }
      return false;
    })
    .Select(x => x.i);