Создание карты :: поиск недействителен
Способствует ли метод map :: find безопасному регистру поиска?
У меня есть карта следующим образом
map<string,vector > directory;
и хотите, чтобы нижестоящий поиск игнорировал регистр.
directory.find(search_string);
- Итерации ключей на карте C ++
- Как получить случайный элемент из контейнера C ++?
- Может ли std :: vector emplace_back копировать конструкцию из элемента самого вектора?
- Как взорвать вектор строк в строку (элегантный способ)
- c ++ сортировка, отслеживающая индексы
- Почему значение, принимающее функции члена setter, не рекомендуется в разговоре с CppCon 2014 Herb Sutter (Back to Basics: Modern C ++ Style)?
- Как повторно использовать ostringstream?
- Как отсортировать вектор пар на основе второго элемента пары?
- C ++ Стереть векторный элемент по значению, а не по положению?
- Как перегружать std :: swap ()
- Можно ли предположить, что хранилище векторов STL всегда смежное?
- Какой тип сортировки используется в std :: sort ()?
- сортировка проблем с использованием функции-члена в качестве компаратора
Это не по умолчанию. В качестве третьего аргумента вам придется предоставить собственный компаратор. Следующий fragment поможет вам …
/************************************************************************/ /* Comparator for case-insensitive comparison in STL assos. containers */ /************************************************************************/ struct ci_less : std::binary_function { // case-independent (ci) compare_less binary function struct nocase_compare : public std::binary_function { 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 } };
Используйте его как std::map< std::string, std::vector
ПРИМЕЧАНИЕ : std :: lexicographic_compare имеет некоторые подробные детали. Сравнение строк не всегда просто, если вы рассматриваете локали. См. Эту тему на clc ++, если это интересно.
UPDATE : С C ++ 11 std::binary_function
устарела и не нужна, поскольку типы выводятся автоматически.
struct ci_less { // case-independent (ci) compare_less binary function struct nocase_compare { 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 } };
Вот несколько других альтернатив, в том числе тот, который выполняет значительно быстрее.
#include
Вы можете создать std::map
с тремя параметрами: тип ключей, тип значений и функцию сравнения – строгий слабый порядок (по существу, функция или функтор, действующий как operator<
с точки зрения транзитивности и антирефлексивности) вашего симпатия. Просто определите третий параметр, чтобы сделать «нечувствительным к регистру меньше» (например, <
a по сравнению с нижними строками, которые он сравнивает), и вы получите «карту без учета регистра», которую вы желаете!
Я использую следующее:
bool str_iless(std::string const & a, std::string const & b) { return boost::algorithm::lexicographical_compare(a, b, boost::is_iless()); } std::map > case_insensitive_map(&str_iless);
Если вы не хотите прикасаться к типу карты (чтобы сохранить ее оригинальную простоту и эффективность), но не против использовать более медленную функцию поиска без учета регистра (O (N)):
string to_lower(string s) { transform(s.begin(), s.end(), s.begin(), (int(*)(int)) tolower ); return s; } typedef map map_type; struct key_lcase_equal { string lcs; key_lcase_equal(const string& s) : lcs(to_lower(s)) {} bool operator()(const map_type::value_type& p) const { return to_lower(p.first) == lcs; } }; map_type::iterator find_ignore_case(map_type& m, const string& s) { return find_if(m.begin(), m.end(), key_lcase_equal(s)); }
PS: Может быть, это была идея Роджера Пейта, но не уверена, поскольку некоторые детали были немного выключены (std :: search ?, direct string comparator?)
Нет, вы не можете сделать это с помощью find
как в этом случае будет много совпадений. Например, при вставке вы можете сделать что-то вроде map["A"] = 1
и map["a"] = 2
и теперь, если вы хотите нечувствительность к регистру map.find("a")
каково ожидаемое возвращаемое значение ? Самый простой способ решить эту проблему – вставить строку в карту только в одном случае (в верхнем или нижнем регистре), а затем использовать тот же случай, когда выполняете поиск.
Элементу Compare шаблона карты по умолчанию соответствует двоичный class сравнения «less». Посмотрите на реализацию:
http://www.cplusplus.com/reference/std/functional/less/
Вероятно, вы можете создать свой собственный class, который происходит от binary_function (родительский class до меньшего) и сделать то же сравнение без чувствительности к регистру.
Проверено:
template struct ci_less:std::binary_function { bool operator() (const T& s1,const T& s2) const { return boost::ilexicographical_compare(s1,s2); }}; ... map> x=boost::assign::map_list_of ("One",1) ("Two",2) ("Three",3); cout << x["one"] << x["TWO"] <
Внесите std :: less функцию и сравните, изменив оба варианта на один и тот же случай.
Для C ++ 11 и выше:
#include #include