Улучшить поиск по частичному индексу multi_index_container на основе результатов part_index_search

Чтобы проиллюстрировать мой вопрос, я скопировал приведенный ниже код из примера "Телефонная книга" справочного документа Boost.

struct phonebook_entry
{
  std::string family_name;
  std::string given_name;
  std::string ssn;
  std::string phone_number;
}

И я могу сделать частичный поиск, как показано ниже

// search for Dorothea White's number
phonebook::iterator it=pb.find(boost::make_tuple("White","Dorothea"));

Однако, если мне нужно посчитать количество людей с фамилией "Белый", а затем узнать, сколько "белых" имеют "Доротея" в качестве своего имени, то каков наилучший способ сделать это? Я думаю, что я могу сделать два частичных запроса, с pb.find(boost::make_tuple("White") и pb.find(boost::make_tuple("White","Dorothea"). Но я обеспокоен, приведет ли это к проблема с производительностью? Так как второй запрос не знает о первом запросе и просто выполняет поиск по всему контейнеру. Предоставляет ли Boost что-то вроде следующего:

std::pair<iterator,iterator> partialResults=pb.equal_range("White");
std::pair<iterator, iterator> partialOfPartial=pb.equal_range("Dorothea", partialResults);

Или есть какой-нибудь умный способ сделать это? Не только с точки зрения удобства, но и для производительности.

1 ответ

Решение

Поскольку phonebook имеет составной ключ, он сортируется по заданным именам в пределах фамилий. Так что вы можете позвонить в регулярный std::equal_range в первом результате поиска, чтобы соответствовать пустышку phonebook_entry который определил только "Дороти":

int main() 
{
    phonebook pb; // no initializer_list support for multi_index_container yet
    pb.insert({ "White", "Dorothy", "1" });  
    pb.insert({ "Black", "Dorothy", "2" });  
    pb.insert({ "White", "John",    "3" });  
    pb.insert({ "Black", "John",    "4" });  
    pb.insert({ "White", "Dorothy", "5" });  

   auto const w = pb.equal_range("White");
   auto const d = phonebook_entry{"", "Dorothy", ""};
   auto const wd = std::equal_range(w.first, w.second, d, [](phonebook_entry const& lhs, phonebook_entry const& rhs) {
       return lhs.given_name < rhs.given_name; 
   });
   std::for_each(wd.first, wd.second, [](phonebook_entry const& pbe) { 
       std::cout << pbe.phone_number << "\n"; 
   });
}

Живой пример, который напечатает для "Белого, Дороти" номера телефонов 1 и 5.

Другие вопросы по тегам