J'ai une structure pour stocker des informations sur les personnes et multi_index_contaider pour stocker ces objets. Mult-index utilise pour la recherche par différents critères.Recherche de chaîne partielle dans boost :: multi_index_container
J'ai ajouté plusieurs personnes dans un conteneur et je souhaite trouver une personne par nom de famille. Cela fonctionne très bien, si j'utilise le nom de famille entier. Mais il ne me revient rien si j'essaie de trouver une personne par une partie d'un nom de famille (premières lettres d'un nom de famille).
Comme vous le savez, la recherche de chaîne partielle fonctionne comme un charme pour std::set<string
>. Donc, j'ai seulement enveloppé les chaînes par une structure et perdu cette fonctionnalité.
Voici le code compilable:
#include <iostream>
#include <string>
#include <algorithm>
#include <set>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#define DEFAULT_ADDRESS "Moscow"
#define DEFAULT_PHONE "11223344"
typedef unsigned int uint;
using namespace boost;
using namespace boost::multi_index;
struct person
{
std::string m_first_name;
std::string m_last_name;
std::string m_third_name;
std::string m_address;
std::string m_phone;
person();
person(std::string f, std::string l, std::string t = "", std::string a = DEFAULT_ADDRESS, std::string p = DEFAULT_PHONE) :
m_first_name(f), m_last_name(l), m_third_name(t), m_address(a),
m_phone(p) { }
virtual ~person()
{ /*std::cout << "Destructing person..." << std::endl;*/ }
person& operator=(const person& rhs);
};
typedef multi_index_container<
person,
indexed_by<
ordered_unique<identity<person> >,
ordered_non_unique<
composite_key<
person,
member<person, std::string, &person::m_last_name>,
member<person, std::string, &person::m_first_name>,
member<person, std::string, &person::m_third_name>
>
>
>
> persons_set;
person& person::operator=(const person &rhs)
{
m_first_name = rhs.m_first_name;
m_last_name = rhs.m_last_name;
m_third_name = rhs.m_third_name;
m_address = rhs.m_address;
m_phone = rhs.m_phone;
return *this;
}
bool operator<(const person &lhs, const person &rhs)
{
if(lhs.m_last_name == rhs.m_last_name)
{
if(lhs.m_first_name == rhs.m_first_name)
return (lhs.m_third_name < rhs.m_third_name);
return (lhs.m_first_name < rhs.m_first_name);
}
return (lhs.m_last_name < rhs.m_last_name);
}
std::ostream& operator<<(std::ostream &s, const person &rhs)
{
s << "Person's last name: " << rhs.m_last_name << std::endl;
s << "Person's name: " << rhs.m_first_name << std::endl;
if (!rhs.m_third_name.empty())
s << "Person's third name: " << rhs.m_third_name << std::endl;
s << "Phone: " << rhs.m_phone << std::endl;
s << "Address: " << rhs.m_address << std::endl << std::endl;
return s;
}
struct comp_persons
{
bool operator()(const person& p1, const person& p2) const
{
if (p2.m_last_name.empty()) return false;
return (p1.m_last_name.find(p2.m_last_name) == 0);
}
};
int main()
{
persons_set my_set;
persons_set::nth_index<0>::type &general_index = my_set.get<0>(); // shortcut to the 1st index
persons_set::nth_index<1>::type &names_index = my_set.get<1>(); // shortcut to the 2nd index
// adding persons
general_index.insert(person("Alex", "Johnson", "Somename"));
general_index.insert(person("Alex", "Goodspeed"));
general_index.insert(person("Peter", "Goodspeed"));
general_index.insert(person("Akira", "Kurosava"));
// search via 2nd index (based on last_name)
std::pair<persons_set::nth_index<1>::type::const_iterator, persons_set::nth_index<1>::type::const_iterator>
n_it = names_index.equal_range("Goodspeed");
// this finds nothing
/*std::pair<persons_set::nth_index<1>::type::const_iterator, persons_set::nth_index<1>::type::const_iterator>
n_it = names_index.equal_range("Goodspe");*/
// idea by Kirill V. Lyadvinsky. This code crashes on the start.
// I guess because behaviour of comp_persons differs from default less<> or reloaded operator <
/*std::pair<persons_set::nth_index<1>::type::const_iterator, persons_set::nth_index<1>::type::const_iterator>
n_it = std::equal_range(names_index.begin(), names_index.end(), person("Alex", "Goodspe"), comp_persons());*/
std::copy(n_it.first ,n_it.second,
std::ostream_iterator<person>(std::cout));
return 0;
}
Si vous avez présenté un minimum, _compilable_ code qui réplicats votre problème (et non disséminée dans plusieurs paragraphes texte), vous pourriez obtenir plus de gens prêts à essayer de résoudre votre problème. –
Merci pour votre suggestion. Maintenant, il semble plus joli et la source est compilable. – Titan
Que voulez-vous dire par "recherche de chaîne partielle fonctionne comme un charme pour' std :: set '"? Voir http://codepad.org/IYi8R3cW par exemple. –