这是一个两步过程。定义一个key
应该映射到元素的函数,即在找到最大值的操作之前应用。将事物包装在 lambda 表达式中,定义用于查找最大值的比较。
auto key = [](int x){
return -abs(42 - x);
};
std::max_element(l.begin(), l.end(), [key](int a, int b){
return key(a) < key(b);
});
在这里,我们必须捕获key
在第二个 lambda 函数之外定义的内容。(我们也可以在里面定义它)。你也可以把它放在一个单独的 lambda 函数中。当 42 应该从 lambda 外部参数化时,将其捕获为变量:
int x = 42;
std::max_element(l.begin(), l.end(), [x](int a, int b){
return -abs(x - a) < -abs(x - b);
});
请注意,它std::max_element
返回一个迭代器。要访问值/对它的引用,请在其前面加上*
:
int x = 42;
auto nearest = std::min_element(l.begin(), l.end(), [x](int a, int b){
return abs(x - a) < abs(x - b);
});
std::cout << "Nearest to " << x << ": " << *nearest << std::endl;
您可以很好地将其包装在一个通用find_nearest
函数中:
template<typename Iter>
Iter find_nearest(Iter begin, Iter end,
const typename std::iterator_traits<Iter>::value_type & value)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&value](const T& a, const T& b){
return abs(value - a) < abs(value - b);
});
}
auto a = find_nearest(l.begin(), l.end(), 42);
std::cout << *a << std::endl;
现场演示 find_nearest
:http: //ideone.com/g7dMYI
与您问题中的函数类似的高阶函数argmax
可能如下所示:
template<typename Iter, typename Function>
Iter argmax(Iter begin, Iter end, Function f)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&f](const T& a, const T& b){
return f(a) < f(b);
});
}
您可以使用以下代码调用它,完全符合您问题中的 lambda 函数:
auto a = argmax(l.begin(), l.end(), [](int x) { return -1 * abs(42 - x); });
std::cout << *a << std::endl;
现场演示 argmax
:http: //ideone.com/HxLMap
现在唯一剩下的区别是这个argmax
函数使用了一个基于迭代器的接口,它对应于 C++ 标准算法 ( <algorithm>
) 的设计。使您自己的编码风格适应您正在使用的工具总是一个好主意。
如果你想要一个直接返回值的基于容器的接口,Nawaz 提供了一个很好的解决方案,它需要 decltype-feature 来正确指定返回类型。我决定以这种方式保留我的版本,以便人们可以看到两种替代界面设计。