![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Boost.Locale: Boundary analysisBoost , ,
Boundary analysis BasicsПовышаю. Locale предоставляет инструмент анализа границ, позволяющий разделить текст на символы, слова или предложения и найти подходящие места для разрывов линий.
Повышаю. 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);
Каждый из них предоставляет элементы< Удобство предоставляют также типдефыssegment_indexилиwcboundary_point_index, где префиксы «w», «u16» и «u32» определяют тип символа< Iterating Over SegmentsBasic IterationАнализ сегментов текста выполняется с использованием классаsegment_index. Он обеспечивает двунаправленный итератор, который возвращаетсегментобъекта. Объект сегмента представляет собой пару итераторов, которые определяют этот сегмент и правило, по которому он был выбран. Он может быть автоматически преобразован в< Для проведения граничного анализа сначала создаем индексный объект, а затем повторяем над ним: Например: 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.
// 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из базы данных Татоэбы» будет разделено на следующие сегменты в< "生", "きるか", "死", "ぬか", "、", "それが", "問題", "だ", "。", Анализ границ, проводимый Boost. Локальность намного сложнее, чем простое разделение текста в соответствии с символами белого пространства, даже если вы не совершенны. Using RulesВыбор сегментов может быть настроен с использованием правилиfull_select. Итератор по умолчанию возвращает каждый текстовый сегмент, определенный двумя пограничными точками, независимо от того, как они были выбраны. Таким образом, в приведенном выше примере мы можем видеть текстовые сегменты, такие как «» или «», которые были выбраны в качестве слов. Используя функцию< Например, позвонив 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="生きるか死ぬか、それが問題だ。";
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? И мы хотим извлечь все предложения из текста. Правилапредложенияимеют два варианта:
Естественно, чтобы игнорировать разделители предложений, мы назвали быsegment_index::rule(rule_type v)с параметром sentence_term, а затем запустили итератор. using namespace boost::locale::boundary;
std::string text= "Hello! How\n"
"are you?\n";
map.rule(sentence_term);
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)на< Добавим эту строку: 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::iterator p = map.find(text.begin() + 4);
if(p!=map.end())
std::cout << *p << std::endl;
Буду печатать: be
Если итератор лежит внутри сегмента, этот сегмент возвращается. Если сегмент не соответствует правилам отбора, то сегмент, следующий за запрашиваемой позицией, возвращается. Например, длясловапограничный анализ ссловом_anyправило:
Iterating Over Boundary PointsBasic Iterationborder_point_indexпохож наsegment_indexв своем интерфейсе, но в качестве другой роли. Вместо возврата текстовых фрагментов (сегментс, возвращаетborder_pointобъект, представляющий положение в тексте — базовый итератор, используемый для итерации исходного текста символов C++. Объектborder_pointтакже предоставляет правило().Функция члена, определяющая правило, по которому была выбрана эта граница.
Рассмотрим пример выбора первых двух предложений из текста: using namespace boost::locale::boundary;
// our text sample
std::string const text="First sentence. Second sentence! Third one?";
// Create an index
// 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?";
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: ";
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не указывает на соответствующее положение. Например, для анализа границ слов:
Например, если мы хотим выбрать 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
// 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 |