-1

I have a string s="java" and a map<string,int>M. M contains (Cpp,1), (jAvA,2), (Cobol,3). I have to check if string s matches (case insensitive) with any key in map. Is there any better way than iterating through entire map and check for each record? In this example string s should match with second record in map, as it is case insensitive matching. In following example we are using compareInterval() with sort(). Is there any way that we can use any function with stricmp() and use map M and string s and perform case insensitive matching efficiently?

// 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;

}

aromahola
  • 190
  • 1
  • 12
  • Are you using std::map ? –  Mar 21 '18 at 19:03
  • Not enough info. State the requirements exactly. Is the map presented to your code already built, or do you insert the strings into it? Do you need to retain the original strings, or would it suffice to store lower case versions of them in the map? – Jive Dadson Mar 21 '18 at 19:23
  • How can we tell if it's an exact duplicate if we can't tell precisely what the intended question is? – Jive Dadson Mar 21 '18 at 19:27
  • I am using std::map, I am inserting strings in map, I have to retain the strings as it is. Only comparison should be case insensitive. – aromahola Mar 22 '18 at 06:44

2 Answers2

2

You can use a case-insensitive comparator for your map:

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

This converts strings to lower case when comparing them, so "java", "Java", "jAvA", "JAVA", etc. will all be considered the same string when inserting into the map or looking up values in it.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • yeah, this is working. Can we use stricmp and compare string and map as we are doing for stl::sort by passing function to stl::sort? I updated code for sort in above question. – aromahola Mar 22 '18 at 06:42
0

Is there any better way than iterating through entire map and check for each record?

It needs to be done since you cannot use std::map::find, which will work more efficiently. You can use use std::find_if to reduce some of the boilerplate code but it still means that you are iterating over each item of the map.

But more importantly, if you are going to search for a key using a case insensitive comparison, it will be better to also create the map using a case insensitive compare function/functor. Otherwise, it's possible to have multiple elements in the map such as:

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

Then the search function will not necessarily get you the item you would like have.

R Sahu
  • 204,454
  • 14
  • 159
  • 270