Есть ли быстрый и приятный способ использования linq?
Найти наиболее встречающееся число в списке <int>
Ответ 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);