Ada_Ru форум

Обсуждение языка Ада

[ada_ru] Разбитие строки и подсчёт слов

Оставить новое сообщение

Сообщения

Роман Томченко
[ada_ru] Разбитие строки и подсчёт слов
2019-06-30 11:15:01

Возникла необходимость наваять функцию для выполнения трёх задач: 1 - разбитие строки на слова (по пробелам и знакам препинания)

2 - подсчёт частоты слов в получившемся массиве

3 - выборка наиболее часто встречающихся слов

 

Первая задача выполняется на ура... (промежуточный вывод правильный) Полная функция даёт пустой вывод

 

Сможет ли кто-то подсказать, что я сделал не так?

 

with Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO, Ada.Characters.Handling;

with GNAT.String_Split;

with Ada.Containers.Indefinite_Ordered_Maps, Ada.Containers.Vectors;

use Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO, Ada.Characters.Handling;

 

procedure Main is

package strVector is new Ada.Containers.Vectors(Natural, Unbounded_String); use strVector;

 

type strArray is array(Positive range <>) of Unbounded_String;

txt: Unbounded_String := To_Unbounded_String("");

len: Integer;

 

function find_most_frequent(text: Unbounded_String) return Vector is Tokens: GNAT.String_Split.Slice_Set;

package wordsMap is new Ada.Containers.Indefinite_Ordered_Maps(Unbounded_String, Integer);

use wordsMap;

begin

GNAT.String_Split.Create(S => Tokens,

From => To_String(text),

Separators => " .,:;/?!\|-_=+",

Mode => GNAT.String_Split.Multiple); declare

Split: strArray(1..Natural(GNAT.String_Split.Slice_Count(Tokens))); Result: Vector;

Words: Map;

Index: wordsMap.Cursor;

Inserted: Boolean;

Max: Integer := 0;

begin

for i in Split'Range loop

Split(i) := To_Unbounded_String(To_Lower(GNAT.String_Split.Slice(Tokens,

GNAT.String_Split.Slice_Number(i))));

if Words.Find(Key => Split(i)) = wordsMap.No_Element then Words.Insert(Key => Split(i),

New_Item => 0,

Position => Index,

Inserted => Inserted);

else

Words.Replace_Element(Position => Index,

New_Item => Integer(Element(Index)) + 1); end if;

end loop;

Index := Words.First;

while Index /= wordsMap.No_Element loop

if Element(Index) > max then

max := Element(Index);

end if;

Index := Next(Index);

end loop;

while Index /= wordsMap.No_Element loop

if Element(Index) = max then

Result.Append(Key(Index));

end if;

end loop;

return Result;

end;

end find_most_frequent;

 

begin

txt := To_Unbounded_String("To understand recursion You need first-time to understand recursion...");

len := Integer(Length(find_most_frequent(txt)));

for i in 1..len-1 loop

if find_most_frequent(txt)(i) /= "" then

Put_Line(find_most_frequent(txt)(i));

end if;

end loop;

-- null;

end Main;

Альтернативное решение с использованием Tables (Simple Components for Ada) и без Unbounded_String:

------------------- main.adb ---------------

with Ada.Text_IO; use Ada.Text_IO;

with Tables.Names;

procedure Main is

type Frequency is new Natural;

package Historam_Raw is new Tables (Frequency);

procedure Check_Spelling (Name : String) is null;

function Check_Matched (Source : String; Pointer : Integer) return Boolean is

begin

return True;

end Check_Matched;

package Histogram is new Historam_Raw.Names; -- Case-insensitive

function Find_Most_Frequent (Text: String) return Histogram.Dictionary is Start : Integer := Text'First;

Max : Frequency := 0;

Words : Histogram.Dictionary;

procedure Add (Word : String) is

Offset : constant Integer := Words.Locate (Word);

begin

if Offset > 0 then

Words.Replace (Offset, Words.GetTag (Offset) + 1);

Max := Frequency'Max (Max, Words.GetTag (Offset));

else

Words.Add (Word, 1);

Max := Frequency'Max (Max, 1);

end if;

end Add;

begin

for Index in Text'Range loop

case Text (Index) is

when ' '|'.'|','|':'|';'|'/'|'?'|'!'|'\'|'|'|'-'|'_'|'='|'+' => if Start < Index then

Add (Text (Start..Index - 1));

end if;

Start := Index + 1;

when others =>

null;

end case;

end loop;

if Start <= Text'Last then

Add (Text (Start..Text'Last));

end if;

for Word in reverse 1..Words.GetSize loop

if Words.GetTag (Word) < Max then

Words.Delete (Word); -- Delete less frequent words

end if;

end loop;

return Words;

end Find_Most_Frequent;

List : constant Histogram.Dictionary :=

Find_Most_Frequent ("To understand recursion You need first-time to understand recursion...");

begin

for Index in 1..List.GetSize loop

Put_Line (List.GetName (Index));

end loop;

end Main;

-----------------------------------

Выдача:

recursion

To

understand

 

 

[Non-text portions of this message have been removed]

Думал, проблема в выводе, поменял вывод на заточенный под вектор:

begin

txt := To_Unbounded_String("To understand recursion You need first-time to understand recursion...");

len := Integer(Length(find_most_frequent(txt)));

for i in find_most_frequent(txt).First_Index..find_most_frequent(txt).Last_Index-1 loop

if find_most_frequent(txt)(i) /= "" then

Put_Line(find_most_frequent(txt)(i));

end if;

end loop;

end Main;

 

не помогло

Надо код загрузить и пощупать. Вообще вопрос понятен, как гляну - отпишусь

 

Нд, 30 черв. 2019, 22:31 користувач Роман Томченко ada_ru@forge.ada-ru.org [ada_ru] <ada_ru@yahoogroups.com> пише:

 

Думал, проблема в выводе, поменял вывод на заточенный под вектор:

begin

txt := To_Unbounded_String("To understand recursion You need first-time to understand recursion...");

len := Integer(Length(find_most_frequent(txt)));

for i in

find_most_frequent(txt).First_Index..find_most_frequent(txt).Last_Index-1 loop

if find_most_frequent(txt)(i) /= "" then

Put_Line(find_most_frequent(txt)(i));

end if;

end loop;

end Main;

 

не помогло

 

------------------------------------

Posted by: =?utf-8?b?0KDQvtC80LDQvSDQotC+0LzRh9C10L3QutC+?= <

ada_ru@forge.ada-ru.org>

------------------------------------

 

 

------------------------------------

 

Yahoo Groups Links

 

 

 

 

 

 

[Non-text portions of this message have been removed]

Категорически согласен... посему ловите ссылку, кого заинтересовал вопрос:

http://tr-media.com.ua/fmf_ada.adb

Роман,

 

Мне кажется если коды были хотя бы отформатированы, их бы рассмотрело гораздо большее количество

 

товарищей. Может Вы их и форматировали, но мейлеры часто удаляют

лидирующие пробелы.

 

Лучше присылать коды в прицепе.

 

 

On 01/07/2019 01.15, Роман Томченко ada_ru@forge.ada-ru.org [ada_ru] wrote:

 

 

Возникла необходимость наваять функцию для выполнения трёх задач: 1 - разбитие строки на слова (по пробелам и знакам препинания)

2 - подсчёт частоты слов в получившемся массиве

3 - выборка наиболее часто встречающихся слов

 

 

 

 

[Non-text portions of this message have been removed]

Просто, как зубной порошок. Идем по строке до разделителя, если продстрока от последнего не-разделителя не пуста, вставляем ее в таблицу с частотой один. Если она уже там, увеличиваем частоту на 1. Повторяем процедуру. Попутно вычисляем максисмальную частоту. В конце цикла не забываем вставить последнюю подстроку. Затем, идем по таблице и удаляем все записи с частотой меньше максимума. Готово. Печатаем все записи из таблицы.

Ничего не запрещает то же самое сделать на стандарных контейнерах. Таблица - примерно, тот же map, но заточена под нормальные строки и эффективное сопоставление с подстрокой неопределенной длинны - плавающий правый край. Стандартные контейнеры потребуют Unbounded_String или, может, indefinite варианты, и преобразования к строчным буквам для нормализации поиска. Короче, не очень кошерно.

 

 

[Non-text portions of this message have been removed]

Спасибо kazakov1961 за ответ. Такой вариант работает... Разбираюсь, как работает ))

Изначально в сторону сторонних библиотек не смотрел

" Просто, как зубной порошок. Идем по строке до разделителя, если продстрока от последнего не-разделителя не пуста, вставляем ее в таблицу с частотой один. Если она уже там, увеличиваем частоту на 1. Повторяем процедуру. Попутно вычисляем максисмальную частоту. В конце цикла не забываем вставить последнюю подстроку. Затем, идем по таблице и удаляем все записи с частотой меньше максимума. Готово. Печатаем все записи из таблицы. "

 

" Ничего не запрещает то же самое сделать на стандарных контейнерах. Таблица - примерно, тот же map, но заточена под нормальные строки и эффективное сопоставление с подстрокой неопределенной длинны - плавающий правый край. Стандартные контейнеры потребуют Unbounded_String или, может, indefinite варианты, и преобразования к строчным буквам для нормализации поиска. Короче, не очень кошерно. "

 

Это да... я с to_lowercase намучился просто ужас - постоянно выдавал cannot return reference to temporary object - и хоть ты тресни (

Кстати... как вы на этом "форуме" цитируете сообщения? - у меня он в текстовом виде без единого указания на форматирование - или он BB-коды поддерживает?

Кстати... как вы на этом "форуме" цитируете сообщения? - у меня он в текстовом виде без единого указания на форматирование - или он BB-коды поддерживает?

 

"Форум" этот поверх почтовой рассылки. Пока не поддерживает BB-кодов. Цитировать можно, как обычно цитируют почтовые клиенты, поставив в начале строки знак больше. Если я ничего не путаю :)

Новое сообщение:
Страницы: 1

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти