2008-12-10 10 views
19

¿Existe alguna manera rápida y agradable de utilizar linq?Encuentra el número que ocurre más en una lista <int>

+0

@AakashM, Es casi seguro que por expresiones lambda OP significaba linq, y no algún delegado/enfoque de expresión. No tengo idea de por qué se revertió la edición. – nawfal

+0

@nawfal 1) no hay forma de sospechar lo que este usuario no registrado significaba hace 4 años o menos, y menos aún de estar "casi seguro".2) [tag: find-occurrences] es una etiqueta pobre y, en cualquier caso, inapropiada. 3) La palabra "linq" no es código y, por lo tanto, no debe formatearse como código. En mi opinión, hay tres partes en el mejor cuestionario para editar, pero son perfectamente válidas para la reversión, pero no dudes en llevarlo a meta si no estás de acuerdo. – AakashM

+0

@AakashM Estoy de acuerdo con 3. Sin embargo, la esencia de mi edición fue una pregunta más sensata. Podría haber eliminado la etiqueta inapropiada (?), Y también el formato del código si eso es lo que importa al volver a editar en lugar de revertir. Así que ahora, * en cualquier caso, etiqueta inapropiada *, ¿para qué tipo de preguntas es más adecuada? 2) ¿Qué crees que debe haber significado OP por * lambda expressions *? Mi punto es que ** hay una manera de sospechar ** haber estado en el círculo C# por un tiempo, y es una fuerte sospecha dada la respuesta que OP ha elegido. – nawfal

Respuesta

60

¿Qué tal:

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

o en la sintaxis 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 utilizar esto en varias ocasiones, se podría añadir un método de extensión:

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

Entonces puede usar:

var most = list.MostCommon(); 
+0

Eso es lo que estaba tratando de hacer, pero mi cerebro simplemente no está funcionando en este momento. –

+5

¿Qué pasa si más de un elemento es la respuesta? –

+1

@Varun - buena pregunta; pero no es difícil adaptarse a –

4

No está seguro acerca de las expresiones lambda, pero me

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

  2. Busque en la lista [O (n)] encontrar la pista más larga -longitud.

  3. Escanear de nuevo [O (n)] informando cada número que tenga esa longitud de ejecución.

Esto se debe a que podría haber más de un número que se produce con mayor frecuencia.

0

Alguien pidió una solución donde hay vínculos. Aquí está una puñalada en la que:

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); 
2

Tomado de mi respuesta here:

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 } 

yo fuimos para una prueba de rendimiento entre el enfoque de arriba y David B'sTakeWhile.

fuente = {}, iteraciones = 1000000
mío - 300 ms, el David de - 930 ms

fuente = {1}, iteraciones = 1000000
minas - 1070 ms, el David de - 1560 ms

fuente = 100 + INT con 2 duplicados, iteraciones = 10000
minas - 300 ms, el David de - 500 ms

fuente = 10000 ints aleatorios con aproximadamente 100 + d uplicates, iteraciones = 1000
minas - 1280 ms, de David - 1400 ms

1

Aquí hay otra respuesta, que parece ser rápida. Creo que Nawfal's answer es generalmente más rápido, pero esto podría sombrearlo en largas secuencias.

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); 
} 
+0

Esto merece una actualización también :) – nawfal

+0

@nawfal de hecho, de acuerdo y hecho. – Jodrell

Cuestiones relacionadas