2009-03-26 17 views
7

Tengo una lista que contiene un grupo de cadenas que pueden aparecer más de una vez. Me gustaría tomar esta lista y crear un diccionario de los elementos de la lista como la clave y el recuento de sus ocurrencias como el valor.Creación de un diccionario de recuentos de elementos en una lista

Ejemplo:

List<string> stuff = new List<string>(); 
stuff.Add("Peanut Butter"); 
stuff.Add("Jam"); 
stuff.Add("Food"); 
stuff.Add("Snacks"); 
stuff.Add("Philosophy"); 
stuff.Add("Peanut Butter"); 
stuff.Add("Jam"); 
stuff.Add("Food"); 

y el resultado sería un diccionario que contiene:

"Peanut Butter", 2 
"Jam", 2 
"Food", 2 
"Snacks", 1 
"Philosophy", 1 

tengo una manera de hacer esto, pero no parece como si estuviera utilizando la buena cosas en C# 3,0

public Dictionary<string, int> CountStuff(IList<string> stuffList) 
{ 
    Dictionary<string, int> stuffCount = new Dictionary<string, int>(); 

    foreach (string stuff in stuffList) { 
     //initialize or increment the count for this item 
     if (stuffCount.ContainsKey(stuff)) { 
      stuffCount[stuff]++; 
     } else { 
      stuffCount.Add(stuff, 1); 
     } 
    } 

    return stuffCount; 
} 

Respuesta

20

Puede usar la cláusula de grupo en C# para hacer esto.

List<string> stuff = new List<string>(); 
... 

var groups = from s in stuff group s by s into g select 
    new { Stuff = g.Key, Count = g.Count() }; 

Puede llamar a los métodos de extensión directamente, así que si quieres:

var groups = stuff.GroupBy(s => s).Select(
    s => new { Stuff = s.Key, Count = s.Count() }); 

partir de aquí es un salto a colocarlo en un Dictionary<string, int>:

var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count); 
+0

¿Cómo se añade un OrdenarPor al primer ejemplo? – zadam

+0

@zadam Siempre puede decir 'groups = groups.OrderBy (g => g.Stuff)'; – casperOne

1

una idea sería dar el diccionario una default value de cero, por lo que que está No debe tener un caso especial la primera vez.

+0

Bueno, eso no sería más que mover el código que maneja el caso especial en una clase separada ... – Guffa

0

Bueno, hay no es realmente una mejor manera de hacerlo.

Quizás podría escribir una consulta LINQ que agrupe las cadenas y luego contar cuántas cadenas hay en cada grupo, pero eso no sería tan eficiente como lo que ya tiene.

7

Habría hecho una lista especializada, respaldada por el diccionario y el método add probaría la membresía y aumentaría el recuento si se encontrara.

sorta como:

public class CountingList 
{ 
    Dictionary<string, int> countingList = new Dictionary<string, int>(); 

    void Add(string s) 
    { 
     if(countingList.ContainsKey(s)) 
      countingList[ s ] ++; 
     else 
      countingList.Add(s, 1); 
    } 
} 
Cuestiones relacionadas