51 votes

Rendre la carte :: trouver une opération insensible à la casse

Est-ce que la méthode map :: find prend en charge la recherche insensible à la casse?
J'ai une carte comme suit

 map<string,vector<string> > directory;
 

et veulent que la recherche ci-dessous ignore le cas.

 directory.find(search_string);
 

72voto

Abhay Points 4268

Il ne fait pas par défaut. Vous devrez fournir une coutume comparateur comme troisième argument. L'extrait de code suivant vous aidera...

  /************************************************************************/
  /* Comparator for case-insensitive comparison in STL assos. containers  */
  /************************************************************************/
  struct ci_less : std::binary_function<std::string, std::string, bool>
  {
    // case-independent (ci) compare_less binary function
    struct nocase_compare : public std::binary_function<unsigned char,unsigned char,bool> 
    {
      bool operator() (const unsigned char& c1, const unsigned char& c2) const {
          return tolower (c1) < tolower (c2); 
      }
    };
    bool operator() (const std::string & s1, const std::string & s2) const {
      return std::lexicographical_compare 
        (s1.begin (), s1.end (),   // source range
        s2.begin (), s2.end (),   // dest range
        nocase_compare ());  // comparison
    }
  };

L'utiliser comme std::map< std::string, std::vector<std::string>, ci_less > myMap;

NOTE: std::lexicographical_compare a quelques moindres détails. Comparaison de chaînes de caractères n'est pas toujours simple si vous envisagez de paramètres régionaux. Voir ce fil sur c.l'.c++ si vous êtes intéressé.

23voto

Robert S. Barnes Points 17244

Voici quelques autres alternatives, y compris une qui exécute beaucoup plus rapidement.

 #include    <map>
#include    <string>
#include    <cstring>
#include    <iostream>
#include    <boost/algorithm/string.hpp>

using std::string;
using std::map;
using std::cout;
using std::endl;

using namespace boost::algorithm;

// recommended in Meyers, Effective STL when internationalization and embedded
// NULLs aren't an issue.  Much faster than the STL or Boost lex versions.
struct ciLessLibC : public std::binary_function<string, string, bool> {
    bool operator()(const string &lhs, const string &rhs) const {
        return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ;
    }
};

// Modification of Manuel's answer
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
    bool operator() (const std::string & s1, const std::string & s2) const {
        return lexicographical_compare(s1, s2, is_iless());
    }
};

typedef map< string, int, ciLessLibC> mapLibc_t;
typedef map< string, int, ciLessBoost> mapBoost_t;

int main(void) {
    mapBoost_t cisMap; // change to test other comparitor 

    cisMap["foo"] = 1;
    cisMap["FOO"] = 2;

    cisMap["bar"] = 3;
    cisMap["BAR"] = 4;

    cisMap["baz"] = 5;
    cisMap["BAZ"] = 6;

    cout << "foo == " << cisMap["foo"] << endl;
    cout << "bar == " << cisMap["bar"] << endl;
    cout << "baz == " << cisMap["baz"] << endl;

    return 0;
}
 

6voto

Manuel Points 5396

J'utilise les éléments suivants:

 bool str_iless(std::string const & a, 
               std::string const & b)
{
    return boost::algorithm::lexicographical_compare(a, b,  
                                                     boost::is_iless());
}
std::map<std::string, std::string, 
         boost::function<bool(std::string const &, 
                              std::string const &)> 
         > case_insensitive_map(&str_iless);
 

6voto

Alex Martelli Points 330805

Vous pouvez instancier std::map avec trois paramètres: type de clés, le type de valeurs, et la fonction de comparaison - une faible stricte de la commande (essentiellement, une fonction ou un foncteur de se comporter en operator< en termes de transitivité et anti-réflexivité) de votre goût. Il suffit de définir le troisième paramètre à ne "casse moins-que" (par exemple, par un < sur le lowercase cordes c'est la comparaison) et vous aurez le "non à la casse de la carte" vous le désirez!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X