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

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

10.12.2008 12:55:29
@AakashM, почти наверняка, что под лямбда-выражениями OP подразумевается linq, а не какой-то подход делегат / выражение. Не знаю, почему редактирование было отменено.
nawfal 30.05.2013 08:55:17
@nawfal 1) нет способа заподозрить, что имел в виду этот незарегистрированный пользователь 4+ года назад, а тем более «почти уверен». 2) find-вхождения - плохой и в любом случае неуместный тег. 3) Слово «linq» не является кодом и поэтому не должно быть отформатировано как код. Три, в лучшем случае, сомнительные части, которые, на мой взгляд, могут быть отредактированы, дают прекрасные основания для возврата, но не стесняйтесь переходить к мета, если вы не согласны.
AakashM 30.05.2013 09:09:48
@AakashM Я согласен с 3. Тем не менее, суть моего редактирования была более разумным вопросом. Вы могли бы удалить несоответствующий тег (?), А также форматирование кода, если это то, что имело значение при переопределении, а не при возврате. Так что теперь, в любом случае, неуместный тег , так для каких типов вопросов он больше подходит? 2) что, по вашему мнению, OP должно иметь в виду под лямбда-выражениями ? Я хочу сказать, что есть способ заподозрить , что какое-то время находился в круге C #, и это сильное подозрение, учитывая, что ответ OP выбрал.
nawfal 30.05.2013 09:24:02
5 ОТВЕТОВ
РЕШЕНИЕ

Как насчет:

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();
75
10.12.2008 13:28:08
Это то, что я пытался понять, но мой мозг просто не работает в данный момент.
Nathan W 10.12.2008 13:26:29
Что если ответом является более одного элемента?
Varun Mahajan 10.12.2008 13:34:07
Лучшее решение с родным LINQ. Хотя с MoreLINQ «S MaxBy()можно даже сделать следующее: list.GroupBy(i=>i).MaxBy(g=>g.Count()).Key. Помимо того, что он короче и яснее, теоретически он должен быть более эффективным для больших наборов данных (максимум против сортировки).
Allon Guralnek 31.05.2013 10:03:10
Спасибо Марк. Это позволило мне применять наиболее часто встречающиеся проблемы кмеров без суеты.
Failed Scientist 16.05.2016 05:45:33

Не уверен насчет лямбда-выражений, но я бы

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

  2. Просканируйте список [O (n)], чтобы найти наибольшую длину прогона.

  3. Сканируйте его снова [O (n)], сообщая о каждом числе, имеющем эту длину серии.

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

4
10.12.2008 13:08:37

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

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);
0
10.12.2008 15:22:50

Взято из моего ответа здесь :

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 }

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

источник = {}, итерации = 1000000
мой - 300 мс, Дэвид - 930 мс

источник = {1}, итерации = 1000000
мой - 1070 мс, Дэвид - 1560 мс

источник = 100+ целых с 2 дубликатами, итерации = 10000
мин - 300 мс, Дэвида - 500 мс

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

3
23.05.2017 11:47:35

Вот еще один ответ, который кажется быстрым. Я думаю, что ответ 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);
}
1
23.05.2017 10:30:43