J'utilise std :: Carte de telle manière: J'aimerais avoir toutes les valeurs dont la clé commence par une chaîne particulière (par exemple "AB"). Je peux facilement obtenir le commencement itérateur à l'aide de la carte :: moindre_bound. Mais comment puis-je obtenir une limite supérieure? Dois-je parcourir l'ensemble de l'ensemble à partir de la liaison inférieure et vérifier toutes les touches s'il commence toujours par "AB"? P> P>
3 Réponses :
J'ai trouvé une réponse similaire Découvrez cette page: ( MAP Complexe Trouver une opération ) Code EXERT: P>
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 }
Vous devrez peut-être mentionner qu'il s'agit d'une solution hautement non optimale et une autre datrastructure est en ordre.
class BeginWithKey { public: BeginWithKey(const string key); bool operator()(const string& s,const int x); private: const string& key_; }; BeginWithKey::BeginWithKey(const string key):key_(key) { } bool BeginWithKey::operator()(const string& s, const int& rh) { if(s.length() < key_.length()) return false; bool begin = true; for(int i = 0; i < key_.size() && begin; ++i) begin = (s[i] == key_[i]); return !begin; } int main() { //your code //copying the map object map<string, int> copy = my_map; //removing the strings not beginning with abc BeginWithKey func("abc"); remove_if(copy.begin(), copy.end(), func); return 0; } The code will work with any string key.
Vous pouvez utiliser Boost Filtre Itérateur qui vous donne un "commencement" et un itérateur "fin" d'itérateurs normaux lorsqu'ils donnaient un prédicat (une fonction BOOL qui dit quelles valeurs inclure)
Par exemple: P>
template <class Predicate> boost::filter_iterator<Predicate, map<string,int>::const_iterator> begin(Predicate predicate) const { return boost::make_filter_iterator(predicate, my_map.begin(), my_map.end()); } template <class Predicate> boost::filter_iterator<Predicate, map<string,int>::const_iterator> end(Predicate predicate) const { return boost::make_filter_iterator(predicate, my_map.end(), my_map.end()); } struct isMatch { isMatch(const std::string prefix) {m_prefix = prefix;}; bool operator()(std::string value) { return value.find_first_of(m_prefix) == 0; }; std::string m_prefix; }; //using: isMatch startWithAb("Ab"); auto myBegin = boost::filter_iterator<startWithAb> begin(); auto myEnd = boost::filter_iterator<startWithAb> end();
Dans ce cas particulier
my_map.lower_bound ("AC") code> semble faire ça
Pourquoi ne pas être lié à "AC"? Pas de lettre entre B et C.
J'ai besoin d'une approche plus générale. L'exemple était juste pour décrire le problème. Je peux être n'importe quel type de chaîne et la carte peut contenir n'importe quel type de chaîne.
@Dejwi aussi longtemps que ce dont vous avez besoin est "qui commence par .." Je pense que cela fonctionnera très bien.
Ok, si je cherchais chaque clé, qui commence par "AZ"? La limite inférieure sera évidemment "AZ" et une limite supérieure?
Le plus approprié ici, je suppose, est de définir une fonction de sorte que, une fois que vous atteignez le dernier caractère de votre éventuelle gamme de caractères, vous devez incrémenter le caractère précédent - de sorte que "AZ" deviendrait "BA" , ou similaire.