Подсчет слов в коллекции с помощью LINQ

У меня есть объект StringCollection с 5 словами. 3 из них являются повторяющимися словами. Я пытаюсь создать запрос LINQ, который будет подсчитывать количество уникальных слов в коллекции и выводить их на консоль. Так, например, если в моей StringCollection есть «Дом», «Автомобиль», «Дом», «Собака», «Кошка», то вывод должен быть таким:

House --> 2
Car --> 1
Dog --> 1
Cat --> 1

Любые идеи о том, как создать запрос LINQ для этого?


person Icemanind    schedule 11.06.2010    source источник
comment
Как вы хотите обращаться с корпусом?   -  person Matthew Whited    schedule 12.06.2010
comment
Игнорировать кейс. Кошка и кошка должны рассматриваться как одно и то же слово   -  person Icemanind    schedule 12.06.2010
comment
Все ваши ответы великолепны, за исключением того, что у меня нет метода .GroupBy. Имейте в виду, что я использую объект System.Collections.Specialized.StringCollection для хранения строк, а не массива строк.   -  person Icemanind    schedule 12.06.2010
comment
возможный дубликат c#: метод подсчета вхождений в списке   -  person nawfal    schedule 17.10.2013


Ответы (5)


Попробуйте следующее

var res = from word in col.Cast<string>()
          group word by word into g
          select new { Word = g.Key, Count = g.Count() };
person JaredPar    schedule 11.06.2010
comment
Я считаю, что простое изменение на group word by word.ToLower() исправит это, конечно, все ваши ключи будут в нижнем регистре. - person Matt Greer; 12.06.2010
comment
Честно говоря, его ответ, вероятно, был написан до того, как он был добавлен. - person Matthew Whited; 12.06.2010
comment
Когда я пытаюсь это сделать, я получаю сообщение об ошибке. Имейте в виду, что я использую объект System.Collections.Specialized.StringCollection для хранения строк, а не массива строк. - person Icemanind; 12.06.2010
comment
@icemanind я изменил свой ответ, чтобы иметь дело со слабо типизированной коллекцией. - person JaredPar; 12.06.2010
comment
@Taylor, мой ответ был написан до того, как было добавлено требование к корпусу. - person JaredPar; 12.06.2010

Учитывая, что вы используете StringCollection и хотите игнорировать регистр, вам нужно использовать Enumerable.GroupBy с Enumerable.Cast:

var results = collection.Cast<string>.GroupBy(
        i => i,
        (word, words) => new { Word = word, Count = words.Count() },
        StringComparer.CurrentCultureIgnoreCase
    );

foreach(var wordPair in results)
     Console.WriteLine("Word: \"{0}\" - Count: {1}", wordPair.Word, wordPair.Count);
person Reed Copsey    schedule 11.06.2010

Чтобы построить результат с одним строковым значением...

var stringCollection = new[] { "House", "Car", "house", "Dog", "Cat" };
var result = stringCollection.Cast<string>().GroupBy(
                                  k => k, 
                                  StringComparer.InvariantCultureIgnoreCase)
                             .Select(v => v.Key + " -->" + v.Count())
                             .Aggregate((l,r)=>l+" " + r);
//result = "House -->2 Car -->1 Dog -->1 Cat -->1"

Чтобы поместить каждое значение в другую строку...

var stringCollection = new[] { "House", "Car", "house", "Dog", "Cat" };
var result = stringCollection.Cast<string>().GroupBy(
                                  k => k, 
                                  StringComparer.InvariantCultureIgnoreCase);

foreach (var value in result)
    Console.WriteLine("{0} --> {1}", value.Key, value.Count());
person Matthew Whited    schedule 11.06.2010

Это должно быть так же просто, как:

Console.WriteLine(stringCollection.Distinct().Count());
person Guffa    schedule 11.06.2010
comment
Это покажет уникальные строки, но не количество дубликатов. - person Ray Hayes; 12.06.2010
comment
Это подсчитает количество уникальных строк. поэтому он вернет 4 - person Matthew Whited; 12.06.2010
comment
@Ray & @Matthew: Да, ОП спросил, как подсчитать количество уникальных слов. Теперь, когда пример отформатирован, я понимаю, что это не то, о чем намеревался просить ОП... - person Guffa; 12.06.2010

person    schedule
comment
Нет! Использование ToLower для сравнения строк без учета регистра == facefalm.jpg - person dtb; 12.06.2010