Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Boost.Locale: Boundary analysis

Boost , ,

Boundary analysis

Basics

Повышаю. Locale предоставляет инструмент анализа границ, позволяющий разделить текст на символы, слова или предложения и найти подходящие места для разрывов линий.

Note
This task is not a trivial task.
A Unicode code point and a character are not equivalent, for example: Hebrew word Shalom - "שָלוֹם" that consists of 4 characters and 6 code points (4 base letters and 2 diacritical marks)
Words may not be separated by space characters in some languages like in Japanese or Chinese.

Повышаю. Locale предоставляет 2 основных класса для анализа границ:

Каждый из классов выше использует тип итератора в качестве параметра шаблона. Оба этих класса принимают в своем конструкторе:

  • Флаг, определяющий пограничный анализ, пограничный_тип.
  • Пара итераторов, которые определяют диапазон текста, который должен быть проанализирован.
  • Локальный параметр (если не используется глобальный)

Например:

namespace ba=boost::locale::boundary;
std::string text= ... ;
std::locale loc = ... ;
ba::segment_index<std::string::const_iterator> map(ba::word,text.begin(),text.end(),loc);

Каждый из них предоставляет элементы<begin()>,<end()>и<find()>, которые позволяют итерировать выбранные сегменты или границы в тексте или найти местоположение сегмента или границы для данного итератора.

Удобство предоставляют также типдефыssegment_indexилиwcboundary_point_index, где префиксы «w», «u16» и «u32» определяют тип символа<wchar_t>,<char16_t>и<char32_t>, а префиксы «c» и «s» определяют, используются ли<std::basic_string<CharType>::const_iterator>или<CharType const *>.

Iterating Over Segments

Basic Iteration

Анализ сегментов текста выполняется с использованием классаsegment_index.

Он обеспечивает двунаправленный итератор, который возвращаетсегментобъекта. Объект сегмента представляет собой пару итераторов, которые определяют этот сегмент и правило, по которому он был выбран. Он может быть автоматически преобразован в<std::basic_string>объект.

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

Например:

using namespace boost::locale::boundary;
std::string text="To be or not to be, that is the question."
// Create mapping of text for token iterator using global locale.
ssegment_index map(word,text.begin(),text.end(),gen("en_US.UTF-8"));
// Print all "words" -- chunks of word boundary
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it)
std::cout <<"\""<< * it << "\", ";
std::cout << std::endl;

Буду печатать:

"To", " ", "be", " ", "or", " ", "not", " ", "to", " ", "be", ",", " ", "that", " ", "is", " ", "the", " ", "question", ".",

Это предложение «き be be {\displaystyleиз базы данных Татоэбы» будет разделено на следующие сегменты в<ja_JP.UTF-8>(японский язык):

"生", "きるか", "死", "ぬか", "、", "それが", "問題", "だ", "。", 

Анализ границ, проводимый Boost. Локальность намного сложнее, чем простое разделение текста в соответствии с символами белого пространства, даже если вы не совершенны.

Using Rules

Выбор сегментов может быть настроен с использованием правилиfull_select.

Итератор по умолчанию возвращает каждый текстовый сегмент, определенный двумя пограничными точками, независимо от того, как они были выбраны. Таким образом, в приведенном выше примере мы можем видеть текстовые сегменты, такие как «» или «», которые были выбраны в качестве слов.

Используя функцию<rule()>, мы можем указать двоичную маску правил, которые мы хотим использовать для выбора граничных точек, используяслово,строкуипредложениеграничные правила.

Например, позвонив

map.rule(word_any);

Прежде чем начать процесс итерации, укажите маску выбора, которая захватывает: цифры, буквы, буквы Каны и идеографические символы, игнорирующие все не связанные с словом символы, такие как белое пространство или знаки препинания.

Итак, код:

using namespace boost::locale::boundary;
std::string text="To be or not to be, that is the question."
// Create mapping of text for token iterator using global locale.
ssegment_index map(word,text.begin(),text.end());
// Define a rule
// Print all "words" -- chunks of word boundary
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it)
std::cout <<"\""<< * it << "\", ";
std::cout << std::endl;

Буду печатать:

"To", "be", "or", "not", "to", "be", "that", "is", "the", "question",

А для данного текста = «き . . . » и правиласлово_ideo, пример выше будет напечатан.

"生", "死", "問題",

Вы можете получить доступ к определенным правилам в тех сегментах, где он был выбран, используясегмент::rule()Функция члена. Используя небольшую маску правил.

Например:

using namespace boost::locale::boundary;
std::string text="生きるか死ぬか、それが問題だ。";
ssegment_index map(word,text.begin(),text.end(),gen("ja_JP.UTF-8"));
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it) {
std::cout << "Segment " << *it << " contains: ";
if(it->rule() & word_none)
std::cout << "white space or punctuation marks ";
if(it->rule() & word_kana)
std::cout << "kana characters ";
if(it->rule() & word_ideo)
std::cout << "ideographic characters";
std::cout<< std::endl;
}

напечатать

Segment 生 contains: ideographic characters
Segment きるか contains: kana characters 
Segment 死 contains: ideographic characters
Segment ぬか contains: kana characters 
Segment 、 contains: white space or punctuation marks 
Segment それが contains: kana characters 
Segment 問題 contains: ideographic characters
Segment だ contains: kana characters 
Segment 。 contains: white space or punctuation marks 

Важно отметить, что каждый сегмент определяется парой границ, а правило его конечной точки определяет, выбран он или нет.

В некоторых случаях это может быть не то, как мы на самом деле выглядим.

Например, у нас есть текст:

Hello! How
are you?

И мы хотим извлечь все предложения из текста.

Правилапредложенияимеют два варианта:

  • Разделите текст на точку, где терминатор предложения, как «.!?» обнаружен:предложение_термин
  • Разделите текст на точку, где сепаратор предложений, такой как «канал строки», обнаружен:sentence_sep

Естественно, чтобы игнорировать разделители предложений, мы назвали быsegment_index::rule(rule_type v)с параметром sentence_term, а затем запустили итератор.

using namespace boost::locale::boundary;
std::string text= "Hello! How\n"
"are you?\n";
ssegment_index map(sentence,text.begin(),text.end(),gen("en_US.UTF-8"));
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it)
std::cout << "Sentence [" << *it << "]" << std::endl;

Однако мы получим ожидаемые сегменты:

Sentence [Hello! ]
Sentence [are you?
]

Причина в том, что «How\n» по-прежнему считается предложением, но выбирается по другому правилу.

Это поведение может быть изменено путем установкиsegment_index::full_select(bool)на<true>. Это заставит итератор присоединиться к текущему сегменту со всеми предыдущими сегментами, которые могут не соответствовать требуемому правилу.

Добавим эту строку:

map.full_select(true);

Сразу после "map.rule(sentence_term);" и получить ожидаемый выход:

Sentence [Hello! ]
Sentence [How
are you?
]

Locating Segments

Иногда полезно найти сегмент, на который указывает какой-то конкретный итератор.

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

segment_indexпредоставляетfind(base_iterator p)функцию члена для этой цели.

Эта функция возвращает итератор в сегмет таким образом, чтоpуказывает на.

Например:

text="to be or ";
ssegment_index map(word,text.begin(),text.end(),gen("en_US.UTF-8"));
ssegment_index::iterator p = map.find(text.begin() + 4);
if(p!=map.end())
std::cout << *p << std::endl;

Буду печатать:

be
Note

Если итератор лежит внутри сегмента, этот сегмент возвращается. Если сегмент не соответствует правилам отбора, то сегмент, следующий за запрашиваемой позицией, возвращается.

Например, длясловапограничный анализ ссловом_anyправило:

  • "t |o be" или ", указывает на "to" - итератор в середине сегмента "to".
  • "to |be" или ", указывает на "be" - итератор в начале сегмента "be"
  • "to | be" или ", указывает на "be" - итератор не указывает на сегмент с требуемым правилом, поэтому следующий действительный сегмент выбран "be".
  • «быть или |», указывает на конец как недействительный сегмент.

Iterating Over Boundary Points

Basic Iteration

border_point_indexпохож наsegment_indexв своем интерфейсе, но в качестве другой роли. Вместо возврата текстовых фрагментов (сегментс, возвращаетborder_pointобъект, представляющий положение в тексте — базовый итератор, используемый для итерации исходного текста символов C++. Объектborder_pointтакже предоставляет правило().Функция члена, определяющая правило, по которому была выбрана эта граница.

Note
The beginning and the ending of the text are considered boundary points, so even an empty text consists of at least one boundary point.

Рассмотрим пример выбора первых двух предложений из текста:

using namespace boost::locale::boundary;
// our text sample
std::string const text="First sentence. Second sentence! Third one?";
// Create an index
sboundary_point_index map(sentence,text.begin(),text.end(),gen("en_US.UTF-8"));
// Count two boundary points
sboundary_point_index::iterator p = map.begin(),e=map.end();
int count = 0;
while(p!=e && count < 2) {
++count;
++p;
}
if(p!=e) {
std::cout << "First two sentences are: "
<< std::string(text.begin(),p->iterator())
<< std::endl;
}
else {
std::cout <<"There are less then two sentences in this "
<<"text: " << text << std::endl;
}

Буду печатать:

First two sentences are: First sentence. Second sentence!

Using Rules

Аналогичноsegment_indexborder_point_indexобеспечиваетфункцию члена правила (rule_type mask)для фильтрации пограничных точек, которые нас интересуют.

Он позволяет установитьслово,строкуипредложениеправил фильтрации граничных точек.

Давайте немного изменим пример выше:

// our text sample
std::string const text= "First sentence. Second\n"
"sentence! Third one?";

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

First two sentences are: First sentence. Second

Это не то, чего мы действительно ожидали. В качестве «Второго\n» рассматривается независимое предложение, которое было разделено разделителем линии «Лайн-Фид».

Однако мы можем установить правилоsentence_term, и итератор будет использовать только граничные точки, которые создаются терминаторами предложения, такими как «.!?».

Добавляя:

map.rule(sentence_term);

Сразу после генерации индекса мы получим желаемый результат:

First two sentences are: First sentence. Second
sentence! 

Вы также можете использовать функциюborder_point::rule(), чтобы узнать о причине, по которой эта пограничная точка была создана, сравнивая ее с соответствующей маской.

Например:

using namespace boost::locale::boundary;
// our text sample
std::string const text= "First sentence. Second\n"
"sentence! Third one?";
sboundary_point_index map(sentence,text.begin(),text.end(),gen("en_US.UTF-8"));
for(sboundary_point_index::iterator p = map.begin(),e=map.end();p!=e;++p) {
if(p->rule() & sentence_term)
std::cout << "There is a sentence terminator: ";
else if(p->rule() & sentence_sep)
std::cout << "There is a sentence separator: ";
if(p->rule()!=0) // print if some rule exists
std::cout << "[" << std::string(text.begin(),p->iterator())
<< "|" << std::string(p->iterator(),text.end())
<< "]\n";
}

Выделит следующие результаты:

There is a sentence terminator: [First sentence. |Second
sentence! Third one?]
There is a sentence separator: [First sentence. Second
|sentence! Third one?]
There is a sentence terminator: [First sentence. Second
sentence! |Third one?]
There is a sentence terminator: [First sentence. Second
sentence! Third one?|]

Locating Boundary Points

Иногда полезно найти конкретную пограничную точку по заданному итератору.

border_point_indexпредоставляетитератор find(base_iterator p)Членский состав.

Он возвращает итератор в пограничную точку наp'sместоположении или в следующем за ним месте, еслиpне указывает на соответствующее положение.

Например, для анализа границ слов:

  • Если базовый итератор указывает на «to |be», то возвращенная пограничная точка будет «to |be» (та же позиция).
  • Если базовый итератор указывает на «t |o be», то возвращенная пограничная точка будет «to | be» (следующее действительное положение)

Например, если мы хотим выбрать 6 слов вокруг определенной пограничной точки, мы можем использовать следующий код:

using namespace boost::locale::boundary;
// our text sample
std::string const text= "To be or not to be, that is the question.";
// Create a mapping
sboundary_point_index map(word,text.begin(),text.end(),gen("en_US.UTF-8"));
// Ignore wite space
// define our arbitraty point
std::string::const_iterator pos = text.begin() + 12; // "no|t";
// Get the search range
begin =map.begin(),
end = map.end(),
it = map.find(pos); // find a boundary
// go 3 words backward
for(int count = 0;count <3 && it!=begin; count ++)
--it;
// Save the start
std::string::const_iterator start = *it;
// go 6 words forward
for(int count = 0;count < 6 && it!=end; count ++)
++it;
// make sure we at valid position
if(it==end)
--it;
// print the text
std::cout << std::string(start,it->iterator()) << std::endl;

Это бы напечатало:

 be or not to be, that

Статья Boost.Locale: Boundary analysis раздела может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 20:54:25/0.011504888534546/1