Encuentra el número más frecuente en una lista

¿Hay alguna manera rápida y agradable de usar linq?

Qué tal si:

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

o en syntax de consulta:

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

Por supuesto, si va a usar esto repetidamente, puede agregar un método de extensión:

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

Entonces puedes usar:

 var most = list.MostCommon(); 

No estoy seguro de las expresiones lambda, pero lo haría

  1. Ordene la lista [O (n log n)]

  2. Escanee la lista [O (n)] para encontrar la longitud de recorrido más larga.

  3. Escanee de nuevo [O (n)] informando cada número que tenga esa longitud de recorrido.

Esto se debe a que podría haber más de un número que ocurre más.

Tomado de mi respuesta aquí :

 public static IEnumerable Mode(this IEnumerable input) { var dict = input.ToLookup(x => x); if (dict.Count == 0) return Enumerable.Empty(); 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 } 

Fui a una prueba de rendimiento entre el enfoque anterior y TakeWhile David B.

source = {}, iterations = 1000000
mío – 300 m, de David – 930 m

source = {1}, iterations = 1000000
mío – 1070 m, de David – 1560 m

source = 100+ ints con 2 duplicados, iteraciones = 10000
mío – 300 m, de David – 500 m

fuente = 10000 entradas al azar con más de 100 duplicados, iteraciones = 1000
el mío – 1280 m, el de David – 1400 m

Aquí hay otra respuesta, que parece ser rápida. Creo que la respuesta de Nawfal es generalmente más rápida, pero esto podría sombrearla en largas secuencias.

 public static IEnumerable Mode( this IEnumerable source, IEqualityComparer 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(); } var maxes = new List(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); } 

Alguien pidió una solución donde hay vínculos. Aquí hay una puñalada de eso:

 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 => xi);