2009-03-26 13 views
7

Mam listę zawierającą kilka ciągów, które mogą wystąpić więcej niż jeden raz. Chciałbym wziąć tę listę i zbudować słownik elementów listy jako klucz i liczbę ich wystąpień jako wartość.Budowanie słownika liczby elementów na liście

Przykład:

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

a wynik byłby słownik zawierający:

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

Mam sposób to zrobić, ale nie wydaje się, jakbym wykorzystując dobre rzeczy w 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; 
} 

Odpowiedz

20

Możesz użyć klauzuli grupy w C#, aby to zrobić.

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() }; 

można wywołać metody rozszerzenie bezpośrednio, jak również, jeśli chcesz:

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

Stąd krótka hop go umieścić w Dictionary<string, int>:

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

Jak byś dodać orderby do pierwszego przykładu? – zadam

+0

@zadam Zawsze możesz powiedzieć: 'groups = groups.OrderBy (g => g.Stuff)'; – casperOne

1

Jednym z pomysłów byłoby dać słownika default value od zera, więc wou W pierwszym przypadku nie ma specjalnego przypadku.

+0

Dobrze, że będzie tylko przeniesienie kodu, który obsługuje szczególny przypadek do osobnej klasy ... – Guffa

0

dobrze, nie tak naprawdę nie jest lepszym sposobem na zrobienie tego.

Być może można napisać kwerendę LINQ, która zgrupowałaby łańcuchy, a następnie zliczyć liczbę łańcuchów w każdej grupie, ale nie byłoby to tak skuteczne, jak to, co już masz.

7

Zrobiłbym wyspecjalizowaną listę, która wspierana przez słownik i metoda dodawania testowałaby członkostwo i zwiększałaby liczbę, jeśli zostanie znaleziona.

coś w stylu:

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); 
    } 
} 
Powiązane problemy