2012-01-13 179 views
5

Estoy trabajando en un programa donde el usuario ha de introducir algún tipo de cadena en, y el programa se almacene en una lista o una matriz, y luego contar cuántas veces que el artículo se repitióobtener el número de veces que un elemento se repite en C#

Los tres elementos que se repiten más a continuación se muestran en orden de número de repeticiones descendente (primero tiene 10 repeticiones, segundo tiene 9, tercero tiene 8)

Parecía sencillo. Dado que no tengo idea de cuántas personas van a introducir una cadena, me utiliza una lista, a continuación, seguido este ejemplo:

foreach (string value in list.Distinct()) 
{ 
    System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", value, list.Count(v => v == value)); 
} 

Pero por alguna razón, .Distinct() no aparece después de mi nombre de la lista. ¿Hice algo mal? ¿Tiene esto algo que ver con mi C#, que NO es un C# 3.0? El ejemplo nunca mencionó nada acerca de agregar otra referencia, o similar.

¿Hay alguna otra manera que puedo hacer esto?

+1

¿Qué versión de .Net es – jolySoft

+0

Si estás usando nada más antigua que 3.0, no tendrá acceso al método de extensión Distinct. –

+0

¿Cuál es su resultado esperado y qué resultado está viendo en su lugar? – jrummell

Respuesta

10

.Distinct() es un método de extensión LINQ. Necesitas .NET 3.5+ para usarlo.

Dicho esto, usted no necesita LINQ para hacer lo que quiera. Podrías usar fácilmente otras clases de colección y un poco de aritmética para obtener tus resultados.

// Create a dictionary to hold key-value pairs of words and counts 
IDictionary<string, int> counts = new Dictionary<string, int>(); 

// Iterate over each word in your list 
foreach (string value in list) 
{ 
    // Add the word as a key if it's not already in the dictionary, and 
    // initialize the count for that word to 1, otherwise just increment 
    // the count for an existing word 
    if (!counts.ContainsKey(value)) 
     counts.Add(value, 1); 
    else 
     counts[value]++; 
} 

// Loop through the dictionary results to print the results 
foreach (string value in counts.Keys) 
{ 
    System.Diagnostics.Debug 
     .WriteLine("\"{0}\" occurs {1} time(s).", value, counts[value]); 
} 
+0

.NET 3.5 en realidad (C# 3) –

+0

@ThomasLevesque: Gracias, lo tuve originalmente pero luego me lo adivino. –

+0

y referencia a system.core.dll –

0

¿Qué versión de .NET Framework está utilizando? La versión de marco mínima que incluye este método es .NET 3.5.

Si está utilizando .NET 3.5 o posterior, tiene usted una declaración using System.Linq; en el archivo de código? Si no, esa es probablemente la razón por la cual el método no parece ser accesible. El método Distinct es en realidad un método de extensión definido en la clase Enumerable, que se encuentra en el espacio de nombres System.Linq.

0

Usted tiene que usar al menos C# .NET 3.0 y 3.5, y recordar acerca de la adición using System.Linq;

0

Al igual que con su solución existente, va a requerir .NET 3.5 o superior para que esto funcione, pero aquí está de todos modos ;

var query = list.GroupBy(x => x).OrderByDescending(x => x.Count()).Take(3); 

foreach (var result in query) 
{ 
    Console.WriteLine("\"{0}\" occurs {1} time(s).", result.Key, result.Count()); 
} 
2

Si no tiene C# 3.0, entonces no tiene los métodos de extensión.

Si usted no tiene .NET3.5 entonces usted no tiene ninguno de los métodos de extensión LINQ a llamar como la estática.

Usted puede añadir su propia para un buen número de estas piezas de funcionalidad:

public static IEnumerable<T> Distinct(IEnumerable<T> src, IEqualityComparer<T> eCmp) 
{ 
    Dictionary<T, bool> fakeHashSet = new Dictionary<T, bool>(eCmp); 
    //When I coded for 2.0 I had my own custom HashSet<T>, but that's overkill here 
    bool dummy; 
    foreach(T item in src) 
    { 
    if(!fakeHashSet.TryGetValue(item, out dummy)) 
    { 
     fakeHashSet.Add(item, true); 
     yield return item; 
    } 
    } 
} 
public static IEnumerable<T> Distinct(IEnumerable<T> src) 
{ 
    return Distinct(src, EqualityComparer<T>.Default); 
} 
public delegate TResult Func<T, TResult>(T arg);//we don't even have this :(
public static int Count(IEnumerable<T> src, Func<T, bool> predicate) 
{ 
    int c = 0; 
    foreach(T item in src) 
    if(predicate(item)) 
     ++c; 
    return c; 
} 

Debido a que no tienen una sintaxis de extensión o lamdbas, tenemos que llamar a ellos como:

foreach (string value in Distinct(list)) 
{ 
    System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", value, Count(list, delegate(string v){return v == value;})); 
} 

En definitiva, podemos poner en práctica la mayor parte de LINQ-a-objetos con C# 2.0, y muchos de nosotros lo hizo, pero es lejos de ser tan amable, y por supuesto que no se puede asignar a otros proveedores de la consulta.

En este caso, sin embargo, sería más rápido simplemente haciendo el recuento directamente:

Dictonary<string, int> counts = new Dictionary<string, int>(); 
foreach(string value in list) 
{ 
    if(counts.ContainsKey(value)) 
    counts[value]++; 
    else 
    counts[value] = 1; 
} 
foreach(KeyValuePair<string, int> kvp in counts) 
    System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", kvp.Key, kvp.Value)); 
Cuestiones relacionadas