これは 2 段階のプロセスです。要素にマップさkey
れる関数を定義します。つまり、最大値を見つける操作の前に適用されます。最大値を見つけるための比較を定義するラムダ式で物事をまとめます。
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
、2 番目のラムダ関数の外で定義されたものをキャプチャする必要があります。(内部で定義することもできます)。これを 1 つのラムダ関数に入れることもできます。ラムダの外側から 42 をパラメータ化する必要がある場合は、これを変数としてキャプチャします。
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);
});
}
質問のラムダ関数を正確に使用して、次のコードでこれを呼び出すことができます。
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 を必要とする優れたソリューションを提供しました。私は自分のバージョンをこのままにしておくことにしたので、人々は両方の代替インターフェースデザインを見ることができます.