map :: find方法是否支持不區分大小寫的搜索?
我有一個圖如下製作map ::查找不區分大小寫的操作
map<string,vector<string> > directory;
,並希望下面的搜索忽略大小寫。
directory.find(search_string);
map :: find方法是否支持不區分大小寫的搜索?
我有一個圖如下製作map ::查找不區分大小寫的操作
map<string,vector<string> > directory;
,並希望下面的搜索忽略大小寫。
directory.find(search_string);
它不會默認。您必須提供一個自定義比較器作爲第三個參數。下面的代碼片段將幫助你......
/************************************************************************/
/* 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
}
};
使用它像std::map< std::string, std::vector<std::string>, ci_less > myMap;
注意:性病:: lexicographical_compare有一些細枝末節。如果考慮語言環境,字符串比較並不總是直截了當的。如果感興趣,請參閱c1.C++上的this線程。
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
}
};
不,你不能這樣做,使用find
在這種情況下,將有多個比賽。例如,雖然插入可以讓您完成類似map["A"] = 1
和map["a"] = 2
的操作,但現在如果您想區分大小寫map.find("a")
,則預期返回值是多少?解決這個問題的最簡單方法是隻在一種情況下(大寫或小寫)將字符串插入到映射中,然後在執行查找時使用相同的大小寫。
-1,誤導。不區分大小寫映射的期望值將簡單地爲2(最後一個值寫爲A「==」a「)。映射使用嚴格的弱排序,它們可以具有相同的鍵,任何這樣的鍵都可以互換使用。 – MSalters 2009-11-26 09:44:32
可能會產生誤導。我試圖展示的是,如果您有區分大小寫的映射,則無法使用find()函數以不區分大小寫的方式工作。 – Naveen 2009-11-26 09:54:18
公平點,但這一點會很多例如,如果你已經解釋過std :: map只支持一個索引,它可以區分大小寫而不區分大小寫,但不能同時存在,從這裏可以輕鬆鏈接到'boost :: multi_index',確實支持第二個索引 – MSalters 2009-11-26 13:41:51
映射模板的比較元素默認爲二進制比較類「less」。看看實現:
http://www.cplusplus.com/reference/std/functional/less/
你可以很可能創建自己的類,從binary_function(父類,以更少)得到,做不區分大小寫相同的比較。
您可以參數實例std::map
:鑰匙的類型,值類型和比較功能 - 一個嚴格弱排序(實際上是一個函數或函數對象而言表現得像operator<
的傳遞性和反反射性)你喜歡的。只需定義第三個參數來執行「不區分大小寫」(例如,通過它所比較的小寫字符串上的<
),並且您將擁有所需的「不區分大小寫的地圖」!
執行std :: less函數並通過將兩者都更改爲相同大小進行比較。
如果你不想觸摸地圖類型(保留它的原始的簡單性和效率),但不介意使用較慢的不區分大小寫的查找功能(O(N)):
string to_lower(string s) {
transform(s.begin(), s.end(), s.begin(), (int(*)(int)) tolower);
return s;
}
typedef map<string, int> 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 ?,直接字符串比較器?)
我使用以下命令:
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);
+1對於酷,但哇,這是醜陋的。讓它成爲我的例子中的仿函數,然後輸入地圖。 – 2010-06-09 20:43:57
這裏有一些其他的替代品,包括其中一個顯著執行速度要快。
#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;
}
測試:
template<typename T>
struct ci_less:std::binary_function<T,T,bool>
{ bool operator() (const T& s1,const T& s2) const { return boost::ilexicographical_compare(s1,s2); }};
...
map<string,int,ci_less<string>> x=boost::assign::map_list_of
("One",1)
("Two",2)
("Three",3);
cout << x["one"] << x["TWO"] <<x["thrEE"] << endl;
//Output: 123
對於C++ 11及以後:
#include <strings.h>
#include <map>
#include <string>
namespace detail
{
struct CaseInsensitiveComparator
{
bool operator()(const std::string& a, const std::string& b) const noexcept
{
return ::strcasecmp(a.c_str(), b.c_str()) < 0;
}
};
} // namespace detail
template <typename T>
using CaseInsensitiveMap = std::map<std::string, T, detail::CaseInsensitiveComparator>;
int main(int argc, char* argv[])
{
CaseInsensitiveMap<int> m;
m["one"] = 1;
std::cout << m.at("ONE") << "\n";
return 0;
}
@Abhay。感謝您的回答。但是,我不完全確定這是如何工作的(對STL來說相對較新)。如何定義第三個參數,即比較函數或函數對象做「不區分大小寫」,實際上不區分大小寫的比較。我們不應該使用==運算符來代替。這實際上是如何工作的。我確定我正在做點什麼。 – Ankur 2009-11-26 07:56:43
@Ankur:std :: map通常實現爲某種樹形結構。 find()方法使用用於排序的比較函數(一個既不在前面也不在後面的項目被認爲是相等的 - 也就是嚴格的弱排序)。這允許使用地圖的樹結構在O(logN)時間內執行搜索。謂詞對象非常像一個排序函數;它的operator()接受一個MyMap :: value_type&作爲參考, 並且如果該項目符合您的搜索標準,則返回true。 – Abhay 2009-11-26 08:06:24
@Ankur:同樣,根據std :: map的簽名std :: map,'Compare'是一個'Strict Weak Ordering',其參數類型爲Key。樹是使用這種順序構建的。若要查看數學術語中的嚴格無序排序,請閱讀簡化的SGI文章@ http://www.sgi.com/tech/stl/StrictWeakOrdering.html –
Abhay
2009-11-26 08:20:51