![](/img/trans.png)
[英]How can I find the minimum key value from an std::vector of std::map values?
[英]How can I find the minimum value in a map?
我有一张map
,我想在map
中找到最小值(右侧)。 我是这样做的:
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;
上面的代码工作正常,我可以得到最小值。 但是,当我将此代码放入我的类中时,如下所示,它似乎不起作用:
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;
}
如何让代码与我的班级一起工作? 另外,是否有更好的解决方案,不需要编写额外的compare
功能?
你有几个选择。 “最好”的方法是使用仿函数 ,这是最快的调用:
typedef std::pair<std::string, int> MyPairType;
struct CompareSecond
{
bool operator()(const MyPairType& left, const MyPairType& right) const
{
return left.second < right.second;
}
};
int MyClass::getMin(std::map<std::string, int> mymap)
{
std::pair<std::string, int> min
= *min_element(mymap.begin(), mymap.end(), CompareSecond());
return min.second;
}
(您也可以将CompareSecond
类嵌套在MyClass
。
使用现在的代码,您可以轻松地将其修改为可用。 只需使函数static
并使用正确的语法:
static bool
MyClass::compare(std::pair<std::string, int> i, std::pair<std::string, int> j)
{
return i.second < j.second;
}
int MyClass::getMin(std::map<std::string, int> mymap)
{
std::pair<std::string, int> min = *min_element(mymap.begin(), mymap.end(),
&MyClass::compare);
return min.second;
}
在C ++ 11中,您可以这样做:
auto it = min_element(pairs.begin(), pairs.end(),
[](decltype(pairs)::value_type& l, decltype(pairs)::value_type& r) -> bool { return l.second < r.second; });
或者把它放在这样一个很好的函数中(注意我不是模板大师;这在许多方面可能是错误的):
template<typename T>
typename T::iterator min_map_element(T& m)
{
return min_element(m.begin(), m.end(), [](typename T::value_type& l, typename T::value_type& r) -> bool { return l.second < r.second; });
}
使用C ++ 14,它进一步简化为:
min_element(pairs.begin(), pairs.end(),
[](const auto& l, const auto& r) { return l.second < r.second; });
问题是这个:
bool MyClass::compare
需要调用类的实例。 也就是说,你不能只调用MyClass::compare
,但是你需要someInstance.compare
。 但是, min_element
需要前者。
简单的解决方案是使其static
:
static bool MyClass::compare
// ...
min_element(mymap.begin(), mymap.end(), &MyClass::compare);
这不再需要调用实例,您的代码也没问题。 但是,您可以使用仿函数使其更通用:
struct compare2nd
{
template <typename T>
bool operator()(const T& pLhs, const T& pRhs)
{
return pLhs.second < pRhs.second;
}
};
min_element(mymap.begin(), mymap.end(), compare2nd());
所有这一切都是抓住每对中的第二个并抓住它们,适用于任何一对。 它可以用于一般,但这有点太多了。
如果你需要足够的价值,我建议你使用Boost的Bimap 。 它是一个双向映射,因此键和值都可用于查找。 您只需获取值键映射的前面。
最后,您始终可以跟踪进入地图的最小元素。 每次插入一个新值时,检查它是否低于当前值(并且它应该是指向映射对的指针,将其作为空值启动),如果它更低,则指向新的最低值。 请求最低值变得像解除引用指针一样简单。
我实际上有另一个问题:如果你需要定期获得最小的右侧值,你确定map
是最好的结构吗?
我建议一般使用Boost.MultiIndex
来解决同一组对象索引的多种方法的问题......但是如果你只需要这个“反向映射”位Boost.Bimap
可能会更容易。
这样,在寻找最小值时,您将无法进行线性搜索:)
正如Jonathan Geisler对Timmmm的回答所述 , C ++ 14允许使用auto
类型说明符声明lambda函数参数。 因此,您可以缩短Timmmm基于lambda的min_element
行(并提高其可读性),如下所示:
auto it = std::min_element(std::begin(mymap), std::end(mymap),
[](const auto& l, const auto& r) { return l.second < r.second; });
注1:如果将此行放入MyClass::getMin()
函数中,则必须返回it->second
。 但是,要考虑空地图,您应该按如下方式调整return
行(或类似):
return it == mymap.end() ? -1 : it->second;
注2:正如Lance Diduck所提到的,你应该通过const
引用将地图传递给你的getMin()
函数。 你这样做的方式是创建一个不必要的整个地图副本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.