Токенизатор для полнотекстового

Это должно быть идеальным случаем не изобретения велосипед, но до сих пор мой поиск был напрасно.

Вместо того, чтобы писать тот самостоятельно, я хотел бы использовать существующий токенизатор C++. Маркеры должны использоваться в индексе для полнотекстового поиска. Производительность очень важна, я проанализирую много гигабайтов текста.

Править: Обратите внимание на то, что маркеры должны использоваться в поисковом индексе. Создание таких маркеров не является точной наукой (afaik) и требует некоторой эвристики. Это было сделано в тысячу раз прежде, и вероятно тысячей различных способов, но я не могу даже найти одного из них :)

Какие-либо хорошие указатели?

Спасибо!

17
задан Rabbit 8 April 2010 в 14:52
поделиться

6 ответов

Я написал свой собственный токенизатор как часть системы индексации и поиска с открытым исходным кодом SWISH ++ .

Также есть токенизатор ICU , который обрабатывает Unicode.

0
ответ дан 30 November 2019 в 14:00
поделиться

Если производительность является основной проблемой, вам, вероятно, следует придерживаться старого доброго strtok , который обязательно будет быстрым:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
1
ответ дан 30 November 2019 в 14:00
поделиться

Библиотека регулярных выражений может хорошо работать, если ваши токены не слишком сложны для анализа.

1
ответ дан 30 November 2019 в 14:00
поделиться

Я мог бы изучить std :: stringstream из . C-style strtok имеет ряд проблем с удобством использования, а строки в C-стиле просто неприятны.

Вот ультратривиальный пример преобразования предложения в слова:

#include <sstream>
#include <iostream>
#include <string>

int main(void) 
{
   std::stringstream sentence("This is a sentence with a bunch of words"); 
   while (sentence)
   {
      std::string word;  
      sentence >> word;  
      std::cout << "Got token: " << word << std::endl;
   }
}

janks@phoenix:/tmp$ g++ tokenize.cc && ./a.out
Got token: This
Got token: is
Got token: a
Got token: sentence
Got token: with
Got token: a
Got token: bunch
Got token: of
Got token: words
Got token:

Класс std :: stringstream является «двунаправленным» в том смысле, что он поддерживает ввод и вывод. Вы, вероятно, захотите сделать только один или другой, поэтому вы должны использовать std :: istringstream или std :: ostringstream .

Их прелесть в том, что они также являются std :: istream и std :: ostream соответственно, поэтому вы можете использовать их так же, как std. :: cin или std :: cout , которые, надеюсь, вам знакомы.

Некоторые могут возразить, что использование этих классов дорого; std :: strstream из в основном то же самое, но построено на основе более дешевых строк в стиле C с завершением 0. Возможно, это будет быстрее для вас. Но в любом случае я бы не стал сразу беспокоиться о производительности. Получите что-нибудь работающее, а затем протестируйте его. Скорее всего, вы сможете получить достаточную скорость, просто написав хорошо написанный C ++, который минимизирует создание и уничтожение ненужных объектов. Если все еще недостаточно быстро, вы можете поискать в другом месте. Однако эти классы, вероятно, достаточно быстрые. Ваш ЦП может тратить тысячи циклов на чтение блока данных с жесткого диска или сети.

0
ответ дан 30 November 2019 в 14:00
поделиться

Ну, я бы начал с поиска Boost и ... hop: Boost.Tokenizer

Хорошая вещь? По умолчанию он разбивается на пробелы и знаки препинания, потому что он предназначен для текста, поэтому вы не забудете символ.

Из введения:

#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>

int main(){
   using namespace std;
   using namespace boost;
   string s = "This is,  a test";
   tokenizer<> tok(s);
   for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
       cout << *beg << "\n";
   }
}

// prints
This
is
a
test

// notes how the ',' and ' ' were nicely removed

И есть дополнительные возможности:

  • он может экранировать символы
  • он совместим с итераторами , поэтому вы можете использовать его с istream напрямую ... и, следовательно, с ifstream

и несколькими опциями (например, сохранение пустых токенов и т. д.)

Проверьте это!

0
ответ дан 30 November 2019 в 14:00
поделиться

Вы можете использовать Ragel State Machine Compiler для создания токенизатора (или лексического анализатора).

Сгенерированный код не имеет внешних зависимостей.

Я предлагаю вам посмотреть на пример clang.rl для получения соответствующего примера синтаксиса и использования.

0
ответ дан 30 November 2019 в 14:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: