Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Помогите


Автор: AndreSan 29.5.2009, 00:43
Помогите как подсчитать количество слов в тексте в C#? если дана стринговская строка?

Автор: Partizan 29.5.2009, 02:02
google string.Split

Автор: kuller 29.5.2009, 08:30
AndreSan, Удаляй со строки первым делом все лишние ПРОБЕЛЫ, а затем при помощи Split бей строку по ПРОБЕЛАМ, таким образом ты получишь МАССИВ, длина которго и будет количество слов в строке.
 

Автор: azesmcar 29.5.2009, 08:46
Код

string str = "hello world";
int count = str.Split(new char[]{ ' ' }).Length;

Автор: diadiavova 29.5.2009, 12:20
Думаю, что простой String.Split в данном случае может преподнести ряд сюрпризов. Во-первых: слова в тексте могут разделяться не только пробелами, но и переходами строк(например). Во-вторых: Не во всех текстах соблюдаются все правила форматирования, то есть, если например вместо пробела будет использована табуляция или несколько пробелов, если вопреки правилам знаки препинания будут использоваться вместо пробелов или отделяться пробелами с обеих сторон, во всех этих случаях будет получен неверный результат.
ИМХО - в данном случае более целесообразно воспользоваться методом System.Text.RegularExpressions.Regex.Split

Код

int count = System.Text.RegularExpressions.Regex.Split(str, @"^\W+$").Length;

Вот как-то так.

Автор: Partizan 29.5.2009, 13:40
да просто в string.Split надо передать массив разделителей ...и все дела..

Автор: diadiavova 29.5.2009, 13:52
Вот такой незатейливый код
Код

        static void Main(string[] args)
        {
            string str = "Hellow , world!";
            Console.Write(str.Split(' ',',', '!').Length.ToString());
            Console.ReadKey();
        }

выводит на консоль 5(проверено).
Кроме того: приходится перечислять все возможные разделители. Я уже не говорю о том, что словом в тексте может считаться и более сложная конструкция(например как считать Syste.String одним словом или нет?), и с регекспами можно немного поменять код (использовать Matches вместо Split, что в общем-то надо было сделать с самого начала...ступил) и проблема легко решится.

Автор: diadiavova 29.5.2009, 14:07
Хотя, конечно, можно сделать и так
Код

        static void Main(string[] args)
        {
            string str = "Hellow , world!";
            string[] sep = {" ",",","!" };
            Console.Write(str.Split(sep,StringSplitOptions.RemoveEmptyEntries).Length.ToString());
            Console.ReadKey();
        }

Но от необходимости перечисления всех возможных разделителей это не избавляет. smile 

Автор: PashaPash 29.5.2009, 14:36
Хакеры.
Код

            string str = "Hellow , world!";
            Console.Write(Regex.Matches(str, @"\b").Count / 2);
            Console.ReadKey();

Автор: diadiavova 30.5.2009, 22:30
Вообще-то: рекомендовать конкретный шаблон регулярного выражения в данном случае несколько преждевременно. Сначала неплохо было бы выяснить у топикастера насколько строг формат входной строки и по каким признакам следует выявлять слова. Есть некоторые сомнения по поводу корректности результатов, которые можно получить с помощью способа, предложенного PashaPash, например в случае, если в тексте появятся строки вроде этих

Код

Ту-144
3,14159
6,673E-11
30.05.2009
+7(495)1234567
+7(812)123-4-321
когда-нибудь
сту́пень
обов'язково


Поэтому считать, что проблему можно решить для всех случаев паттерном из одного спецсимвола, на мой взгляд - слишком смело. 
Хотя, есть подозрение, что топикастеру это не нужно и тем не менее...

Автор: source777 1.6.2009, 22:31
Цитата(diadiavova @  30.5.2009,  22:30 Найти цитируемый пост)
Поэтому считать, что проблему можно решить для всех случаев паттерном из одного спецсимвола, на мой взгляд - слишком смело. 

В любом случае, я считаю метод предложенный PashaPash, единственным разумным из предложенных здесь, т.к. я лично не понял нафига здесь Split, когда нужно подсчитать количество слов. Единственное что требуется уточнить так это понятие слова, если в рамках задачи это понятие не совпадает с понятием слова используемом в регулярных выражениях(\b - граница слова), то правильным решением будет:
Код

var pattern = @"[a-zA-Zа-яёА-ЯЁ-]+"; // шаблон для слова в рамках конкретной задачи
var count = Regex.Matches(str, pattern).Count;

Автор: diadiavova 1.6.2009, 22:51
source777, после того, как все в один голос стали писать о том, что проблема решается методом стрингсплит, я обратил внимание на тот факт, что  результаты, выдаваемые им будут далеко не всегда корректными, и что в данном случае целесообразно использовать регекспы. Код, приведённый мной в том посте был всего-навсего примером. Далее я упомянул и об использовании Matches(если ты заметил, конечно). Код, предложенный PashaPash - совсем не плох, если не считать того обстоятельства, что единственным, содержащимся в нём новшеством был именно шаблон, о недостатках которого я и написал. А что использовать Split или  Matches - это вообще дело вкуса(и конкретных обстоятельств ессно).

Добавлено через 6 минут и 37 секунд
И кстати если конкретная задача подразумевает, что слова состоят только из алфавитных символов(без цифр), то можно сделать так
Код

[\w-[\d]]+

Автор: source777 1.6.2009, 23:37
Цитата(diadiavova @  1.6.2009,  22:51 Найти цитируемый пост)
Далее я упомянул и об использовании Matches(если ты заметил, конечно)
Не заметил, надо было в коде упомянуть...  smile 


Цитата(diadiavova @  1.6.2009,  22:51 Найти цитируемый пост)
А что использовать Split или  Matches - это вообще дело вкуса(и конкретных обстоятельств ессно).
Split`у нужно указывать именно разделители, в этом есть разница.

Автор: diadiavova 1.6.2009, 23:44
Цитата(source777 @  1.6.2009,  23:37 Найти цитируемый пост)
Не заметил, надо было в коде упомянуть...

Берёшься спорить - читай всё smile 

Цитата(source777 @  1.6.2009,  23:37 Найти цитируемый пост)
Split`у нужно указывать именно разделители, в этом есть разница.

Из моего предыдущего шаблона. Вот, что надо указать Matches
Код

[\w-[\d]]+

И вот, что сплиту
Код

[^\w-[\d]]+

Что называется "почувствуйте разницу". Кроме того сплит возвращает строковый массив, а иногда нужен именно он. Так что разница не только в том, о чём упомянул ты.

Автор: Partizan 2.6.2009, 01:54
Да, исходя из постановки задачи решение с Regex.Matches выглядит более правильным smile
Я изначально предложил string.Split, ибо синтаксиса построения регулярных выражений особо не знаю smile

Автор: PashaPash 2.6.2009, 07:48
Цитата(diadiavova @  1.6.2009,  22:51 Найти цитируемый пост)
Код, предложенный PashaPash - совсем не плох, если не считать того обстоятельства, что единственным, содержащимся в нём новшеством был именно шаблон, о недостатках которого я и написал. 

Чем тебя не устраивает шаблон \b? Это хоть как-то стандартизированная граница слова. В русском дефис - не разбивает слово. В каком нибудь гондурасском - разбивает. Точный способ посчитать количество слов - взять софт с хоть какими нибудь функциями верстки - тот же word, скормить текст ему и подождать. В любом случае взять готовый стандратный символ - лучше, чем составлять таблицу разделителей. 
Цитата(diadiavova @  1.6.2009,  22:51 Найти цитируемый пост)
И кстати если конкретная задача подразумевает, что слова состоят только из алфавитных символов(без цифр), то можно сделать так

А если не подразумевает? Word считает 42 словом ;). И этот смайлик тоже.

Автор: diadiavova 2.6.2009, 11:11
Цитата(Partizan @  2.6.2009,  01:54 Найти цитируемый пост)
синтаксиса построения регулярных выражений особо не знаю

Я - тоже(особо). Здесь надо сказать, что во многих случаях использования стрингсплита может оказаться достаточно, в частности, веб-браузеры работают примерно по такой же логике, там от пробелов может зависеть распределение текста. Я, собственно, только указал на возможные ошибки и способ их избежать. Честно говоря мне не очень понятно, почему тема потихоньку начинает превращаться в холивар.
Цитата(PashaPash @  2.6.2009,  07:48 Найти цитируемый пост)
Чем тебя не устраивает шаблон \b? Это хоть как-то стандартизированная граница слова.

Хотябы тем, что слово, полученное таким образом может включать цифры, но при этом не включает ряд символов, которые так же могут содержаться в словах. К каким последствиям это может привести я показал в примерах. Целое число считается одним словом, а дробное иногда двумя, а иногда тремя итд.
Исправить такое положение вещей можно только полной заменой шаблона. (кстати: мой шаблон, приведённый для примера, делит текст по той же логике, что и твой)
Цитата(PashaPash @  2.6.2009,  07:48 Найти цитируемый пост)
В русском дефис - не разбивает слово. В каком нибудь гондурасском - разбивает. 

Поэтому я и пишу, что предлагать конкретные шаблоны, не зная задачи топикастера, - преждевременно.
Цитата(PashaPash @  2.6.2009,  07:48 Найти цитируемый пост)
В любом случае взять готовый стандратный символ - лучше, чем составлять таблицу разделителей. 

Не влюбом. Только в том, который решает задачу корректно.


Цитата(PashaPash @  2.6.2009,  07:48 Найти цитируемый пост)
Цитата(diadiavova @  1.6.2009,  22:51 Найти цитируемый пост)
И кстати если конкретная задача подразумевает, что слова состоят только из алфавитных символов(без цифр), то можно сделать так

А если не подразумевает? Word считает 42 словом ;). И этот смайлик тоже.

Это был ответ другому участнику, предложившему в шаблоне перечислить алфавитные символы. Я просто указал, что это можно сделать иначе. 

ЗЫ
И кстати: в Гондурасе говорят на испанском smile 

Автор: PashaPash 2.6.2009, 12:15
Цитата(diadiavova @  2.6.2009,  11:11 Найти цитируемый пост)

Не влюбом. Только в том, который решает задачу корректно.

Неизвестная задача - это "любой" случай smile

Автор: diadiavova 2.6.2009, 12:21
Цитата(PashaPash @  2.6.2009,  12:15 Найти цитируемый пост)
Неизвестная задача - это "любой" случай 

То есть, если тебе задача не вполне понятна, то можно дать любой ответ?

Автор: PashaPash 2.6.2009, 13:02
diadiavova, нет, просто подходящий в большинстве случаев. И заодно соответствующий хоть какому-то общепринятому стандарту.

Автор: diadiavova 2.6.2009, 13:33
Я, вроде как, привёл список случаев, в которых он возвращает некорректные результаты. ИМХО гораздо правильнее описать с какими "подводными камнями" можно столкнуться при решении этой задачи, чем давать решение, которое может и не подойти. 

Я уже не говорю о том, что твой метод с вычислением границ слов и последующим их делением пополам, лично мне кажется слегка экзотическим. Почему было не сделать так \w+?

Автор: PashaPash 2.6.2009, 14:17
Цитата(diadiavova @  2.6.2009,  13:33 Найти цитируемый пост)
Я, вроде как, привёл список случаев, в которых он возвращает некорректные результаты. ИМХО гораздо правильнее описать с какими "подводными камнями" можно столкнуться при решении этой задачи, чем давать решение, которое может и не подойти. 

В каком смысле некорректные? Считает "-" и скобки разделителем? так ты сам это условие ввел smile

По версии ворда вот тут "Это – тоже слово !" - 4 слова. А вот тут - "Это - тоже слово !" - уже 5. Хотя здравый смысл подсказывает что слов тут всего 3. Ворд некорректен? Давай любой алгорим, я тут же дам пример когда он некорректен.

Цитата(diadiavova @  2.6.2009,  13:33 Найти цитируемый пост)
Я уже не говорю о том, что твой метод с вычислением границ слов и последующим их делением пополам, лично мне кажется слегка экзотическим. Почему было не сделать так \w+?

А как же внутренняя красота кода? smile "\b" / 2, IMHO, намного красивее, чем сплит по "^\W+$" ;)

Автор: Partizan 2.6.2009, 14:29
PashaPash, 
diadiavova, 

...думаю автор получил ответ на свой вопрос и топик исчерпан...

 smile 

Осталось мне только самому себе предупреждение выписать за провокацию споров string.Split-ом =)))

Автор: diadiavova 2.6.2009, 15:10
PashaPash, я, как бы, с самого начала твержу о том, что задача требует уточнения. Именно по тем же причинам.
Цитата(PashaPash @  2.6.2009,  14:17 Найти цитируемый пост)
А как же внутренняя красота кода?

Красота - понятие субъективное.

Partizan, Извини - так вышло smile

Автор: jonie 2.6.2009, 21:03
а можно прикрутить спелчекер и "перестраховываться"...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)