2009-02-17 5 views
4

Я хочу сделать следующее:
Определить карту между строкой и любым объектом (может быть список, целое - что угодно).
Ключи к карте может быть следующим (значения, опять же, не имеет значения):
"ААА/123" ==> 1
"ААА/" ==> 2
«ВВВ/
"==> 3
"CCC/*" ==> 4
"CCC/123" ==> 5
Теперь фокус в том, я хочу, чтобы найти правильные значения, приведенные следующие строки:
" AAA/123 "следует указать 1.
" AAA/111 "должно указывать 2.
" CCC/111 "должно предоставить 4.
"CCC/123" должны дать 5.
"BBB/AAA/123" должен дать 3.карта операция наложения

Любая идея, как я могу это сделать с C++ и, возможно, STL/увеличить?

+0

я удалил свой ответ, потому что я не думал достаточно :) Я думаю, что trie идеально подходит для этой утилиты. просто двигайтесь по дорожкам trie, пока не будет найдено больше совпадающих элементов.посмотрите здесь: http://en.wikipedia.org/wiki/Trie. –

ответ

3

Вот вариант LITB ответа (который был каким-то образом удален из списка ответов), которые могли бы работа, учитывая «*» удаляется:

template<typename Map> typename Map::const_iterator 
find_prefix(Map const& map, typename Map::key_type const& key) 
{ 
    typename Map::const_iterator it = map.upper_bound(key); 
    while (it != map.begin()) 
    { 
     --it; 
     if(key.substr(0, it->first.size()) == it->first) 
      return it; 
    } 

    return map.end(); // map contains no prefix 
} 

Я забыл добавить код, который использует его:

std::map<std::string, int> smap; 
smap["AAA/"] = 1; 
smap["BBB/"] = 2; 
smap["AAA/AA"] = 3; 

find_prefix(smap, "AAA/AB")->second; // ==> 1 
find_prefix(smap, "AAA/AA")->second; // ==> 3 
find_prefix(smap, "BBB/AB")->second; // ==> 2 
find_prefix(smap, "CCC/AB"); // ==> smap.end() 

любой комментарий (и спасибо)

+0

Да, это хорошее обходное решение, я думаю. если на вашей карте много элементов, вы также можете последовательно вызвать find_prefix, причем строка поиска всегда будет меньше по размеру. что позволит избежать линейного поиска в зависимости от размера карты, но теперь в зависимости от размера строки поиска. –

+0

, но я не знаю, действительно ли это будет быстрее. im немного плохой с таким анализом :) возможно, некоторые тесты в порядке :) –

+0

Поскольку моя карта должна быть слишком большой (до нескольких десятков записей), а ключ также ограничен одним и тем же номером более или менее (как долго строка может быть?) - Я думаю, это не имеет значения, какой путь самый быстрый. – Guy

1

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

Я думаю, что структура, подобная этой std :: map, может вам помочь. Boost :: любой сможет хранить что-либо, но предостережение в том, что вам нужно знать, что тип значения должен его прочитать.

Ключ - это строка и, следовательно, это тоже выражение регулярных выражений. С этой структурой вам потребуется два алгоритм прохода, как:

std::map<std::string, boost::any> _map; 
if (_map.find(key) != _map.end) 
{ 
    // exact match 
} 
else 
{ 
    // Have to do sequential regex (use boost::regex) matching 
} 

Поскольку регулярное выражение оценка во время выполнения может быть дорогостоящей, вы можете использовать зЬй :: вектора>, такие, что для регулярных выражений шаблонов хранить скомпилированные регулярные выражения в одно из полей ,

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

0

Как использовать две карты?

std::map<std::string, std::map<int, object> > 

Если вы хотите для поиска ааа/* вы

a.find("aaa") => you get an iterator to the map with all "aaa" prefix 

Если вы хотите для поиска ааа/123 вы

a.find("aaa")->find(123) 

(конечно, вы должны подтвердить, что вы не 't конец, это только для примера)

+0

Что делать, если префикс не только «aaa», но также может быть «aaa/bbb»? – Guy

+0

Если вы хотите что-то эффективное, вам нужно придумать четкие правила. Какова ваша конечная цель? –