Emadpres
Emadpres

Reputation: 3747

How not to use custom comparison function of std::map in searching ( map::find)?

As you can see in my code, lenMap is a std::map with a custom comparison function. This function just check the string's length.

Now when I want to search for some key ( using map::find), the map still uses that custom comparison function.

But How can I force my map not to use that when I search for some key ?

Code:

struct CompareByLength : public std::binary_function<string, string, bool>
{
    bool operator()(const string& lhs, const string& rhs) const
    {
        return lhs.length() < rhs.length();
    }
};

int main()
{
    typedef map<string, string, CompareByLength> lenMap;
    lenMap mymap;

    mymap["one"] = "one";
    mymap["a"] = "a";
    mymap["foobar"] = "foobar";

    // Now In mymap: [a, one, foobar]

    string target = "b";
    if (mymap.find(target) == mymap.end())
        cout << "Not Found :) !";
    else
        cout << "Found :( !"; // I don't want to reach here because of "a" item !

    return 0;
}

Upvotes: 1

Views: 860

Answers (2)

Neil Kirk
Neil Kirk

Reputation: 21813

The comparison function tells the map how to order elements and how to differentiate between them. If it only compares the length, two different strings with the same length will occupy the same position in the map (one will overwrite the other).

Either store your strings in a different data structure and sort them, or perhaps try this comparison function:

struct CompareByLength
{
    bool operator()(const string& lhs, const string& rhs) const
    {
        if (lhs.length() < rhs.length())
        {
            return true;
        }
        else if (rhs.length() < lhs.length())
        {
            return false;
        }
        else
        {
            return lhs < rhs;
        }
    }
};

I didn't test it, but I believe this will first order strings by length, and then however strings normally compare.

You could also use std::map<std::string::size_type, std::map<std::string, std::string>> and use the length for the first map and the string value for the second map. You would probably want to wrap this in a class to make it easier to use, as there is no protection against messing it up.

Upvotes: 0

TheOperator
TheOperator

Reputation: 6516

The map itself does not offer such an operation. The idea of the comparison functor is to create an internal ordering for faster lookup, so the elements are actually ordered according to your functor.

If you need to search for elements in a different way, you can either use the STL algorithm std::find_if() (which has linear time complexity) or create a second map that uses another comparison functor.

In your specific example, since you seem only to be interested in the string's length, you should rather use the length (of type std::size_t) and not the string itself as a key.

By the way, std::binary_function is not needed as a base class. Starting from C++11, it has even been deprecated, see here for example.

Upvotes: 1

Related Questions