Home:ALL Converter>How can I find the minimum value in a map?

How can I find the minimum value in a map?

Ask Time:2010-04-18T01:11:21         Author:Sunny

Json Formatter

I have a map and I want to find the minimum value (right-hand side) in the map. Here is how I did it:

bool compare(std::pair<std::string ,int> i, pair<std::string, int> j) {
  return i.second < j.second;
}
////////////////////////////////////////////////////
std::map<std::string, int> mymap;

mymap["key1"] = 50;
mymap["key2"] = 20;
mymap["key3"] = 100;

std::pair<char, int> min = *min_element(mymap.begin(), mymap.end(), compare); 
std::cout << "min " << min.second<< " " << std::endl;

The code above works fine and I'm able to get the minimum value. However, when I put this code inside my class as follows, it doesn't seem to work:

int MyClass::getMin(std::map<std::string, int> mymap) {
  std::pair<std::string, int> min = *min_element(mymap.begin(), mymap.end(), 
                                                 (*this).compare);
                                                 // Error probably due to "this".
  return min.second; 
}

bool MyClass::compare(
    std::pair<std::string, int> i, std::pair<std::string, int> j) { 
  return i.second < j.second; 
}

How can I make the code work with my class? Also, is there a better solution which doesn't require writing the additional compare function?

Author:Sunny,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/2659248/how-can-i-find-the-minimum-value-in-a-map
Timmmm :

In C++11 you can do this:\n\nauto it = min_element(pairs.begin(), pairs.end(),\n [](decltype(pairs)::value_type& l, decltype(pairs)::value_type& r) -> bool { return l.second < r.second; });\n\n\nOr put it in a nice function like this (note I'm not a template guru; this is probably wrong in many ways):\n\ntemplate<typename T>\ntypename T::iterator min_map_element(T& m)\n{\n return min_element(m.begin(), m.end(), [](typename T::value_type& l, typename T::value_type& r) -> bool { return l.second < r.second; });\n}\n\n\n\n\nWith C++14, it further simplifies to:\n\nmin_element(pairs.begin(), pairs.end(),\n [](const auto& l, const auto& r) { return l.second < r.second; });\n",
2014-11-10T11:41:37
rlbond :

You have a few options. The \"best\" way to do this is with a functor, this is guaranteed to be the fastest to call:\n\ntypedef std::pair<std::string, int> MyPairType;\nstruct CompareSecond\n{\n bool operator()(const MyPairType& left, const MyPairType& right) const\n {\n return left.second < right.second;\n }\n};\n\n\n\nint MyClass::getMin(std::map<std::string, int> mymap) \n{\n std::pair<std::string, int> min \n = *min_element(mymap.begin(), mymap.end(), CompareSecond());\n return min.second; \n}\n\n\n(You can also nest the CompareSecond class inside MyClass.\n\nWith the code you have now, you can easily modify it to work, however. Just make the function static and use the correct syntax:\n\nstatic bool \nMyClass::compare(std::pair<std::string, int> i, std::pair<std::string, int> j) \n{ \n return i.second < j.second; \n}\n\nint MyClass::getMin(std::map<std::string, int> mymap) \n{\n std::pair<std::string, int> min = *min_element(mymap.begin(), mymap.end(), \n &MyClass::compare);\n return min.second; \n}\n",
2010-04-17T17:18:35
honk :

C++14\n\nAs mentioned in Jonathan Geisler's comment on Timmmm's answer, C++14 allows lambda function parameters to be declared with the auto type specifier. As a result, you can shorten Timmmm's lambda-based min_element line (and improve its readability) as follows:\n\nauto it = std::min_element(std::begin(mymap), std::end(mymap),\n [](const auto& l, const auto& r) { return l.second < r.second; });\n\n\nNote 1: If you put this line into your MyClass::getMin() function, you have to return it->second. However, to account for an empty map, you should adapt the return line as follows (or similar):\n\nreturn it == mymap.end() ? -1 : it->second;\n\n\nNote 2: As also mentioned by Lance Diduck, you should be passing the map by const reference to your getMin() function. The way you did it, you are creating an unnecessary copy of the whole map.\n\nCode on Ideone",
2019-06-06T14:03:57
GManNickG :

The problem is that this:\n\nbool MyClass::compare\n\n\nRequires an instance of the class to be called on. That is, you can't just call MyClass::compare, but you need someInstance.compare. However, min_element needs the former.\n\nThe easy solution is to make it static:\n\nstatic bool MyClass::compare\n\n// ...\n\nmin_element(mymap.begin(), mymap.end(), &MyClass::compare);\n\n\nThis no longer requires an instance to be called on, and your code will be fine. You can make it more general with a functor, though:\n\nstruct compare2nd\n{\n template <typename T>\n bool operator()(const T& pLhs, const T& pRhs)\n {\n return pLhs.second < pRhs.second;\n }\n};\n\nmin_element(mymap.begin(), mymap.end(), compare2nd());\n\n\nAll this does is grab the second from each pair and grab them, works with any pair. It could be made for general, but that's a bit too much.\n\nIf you need to look up by value enough, I recommend you use Boost's Bimap. It's a bi-directional map, so both the key and value can be used to lookup. You would simply get the front of the value-key map.\n\nLastly, you can always just keep track of the minimum element going into your map. Every time you insert a new value, check if it's lower than your current value (and that should be probably be a pointer to a map pair, start it as null), and if it's lower, point to the new lowest. Requesting the lowest becomes as simple as dereferencing a pointer.",
2010-04-17T17:30:36
yy