字符串和映射的不区分大小写的比较

时间:2018-03-21 18:58:26

标签: c++ algorithm dictionary

我有string s="java"map<string,int>MM包含 (Cpp,1), (jAvA,2), (Cobol,3)。我必须检查string s是否与地图中的任何键匹配(不区分大小写)。 Is there any better way than iterating through entire map and check for each record?在此示例中,字符串s应与map中的第二个记录匹配,因为它不区分大小写匹配。在以下示例中,我们将compareInterval()sort()一起使用。有没有办法可以使用stricmp()的任何函数并使用map M和string s并有效地执行不区分大小写的匹配?

// A C++ program to demonstrate STL sort() using
// our own comparator
#include<bits/stdc++.h>
using namespace std;

// An interval has start time and end time
struct Interval
{
   int start, end;
};

// Compares two intervals according to staring times.
bool compareInterval(Interval i1, Interval i2)
{
   return (i1.start < i2.start);
}

int main()
{
  Interval arr[] =  { {6,8}, {1,9}, {2,4}, {4,7} };
  int n = sizeof(arr)/sizeof(arr[0]);

// sort the intervals in increasing order of
// start time
sort(arr, arr+n, compareInterval);

cout << "Intervals sorted by start time : \n";
for (int i=0; i<n; i++)
   cout << "[" << arr[i].start << "," << arr[i].end
        << "] ";

return 0;

}

2 个答案:

答案 0 :(得分:1)

您可以为地图使用不区分大小写的比较器:

struct CaseInsensitiveLess
{
    bool operator()(std::string lhs, std::string rhs)
    {
        std::transform(lhs.begin(), lhs.end(), lhs.begin(),
                       [](char c) { return std::tolower(c); });
        std::transform(rhs.begin(), rhs.end(), rhs.begin(),
                       [](char c) { return std::tolower(c); });
        return lhs < rhs;
    }
};

int main()
{
    std::map<std::string, int, CaseInsensitiveLess> foo = {
        {"Cpp", 1}, {"jAvA", 2}, {"Cobol", 3}
    };

    std::cout << foo["java"] << '\n';
}

Live Demo

这会在比较字符串时将字符串转换为小写字母,因此在插入时,"java""Java""jAvA""JAVA"等都会被视为相同的字符串地图或查找其中的值。

答案 1 :(得分:0)

  

有没有比迭代整个地图并检查每条记录更好的方法?

需要完成此操作,因为您无法使用std::map::find,这将更有效地工作。您可以使用std::find_if来减少一些样板代码,但仍然意味着您正在迭代map的每个项目。

但更重要的是,如果您要使用不区分大小写的比较来搜索键,最好还使用不区分大小写的比较函数/仿函数来创建映射。否则,map中可能有多个元素,例如:

(jAvA, 2)
(java, 20)
(JAVA, 30)

然后搜索功能不一定能为您提供您想要的项目。