C++ 范围的最小返回值
我想知道是否有一个标准函数可以返回给定元素范围的最小/最大返回值。大概是这样的:C++ 范围的最小返回值,c++,algorithm,c++11,c++14,C++,Algorithm,C++11,C++14,我想知道是否有一个标准函数可以返回给定元素范围的最小/最大返回值。大概是这样的: std::vector<int> list = { -2, -1, 6, 8, 10 }; auto it = std::find_min_return_value(list.begin(), list.end(), std::abs, std::less<int>); // it should be the iterator for -1 修改代码以改用有状态lambda后:
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto it =
std::find_min_return_value(list.begin(), list.end(), std::abs, std::less<int>);
// it should be the iterator for -1
修改代码以改用有状态lambda后:
for(int i = 0; i < 10000000; ++i)
{
auto it = std::min_element(list.begin() + 1, list.end(),
[&, current_min_value = semi_expensive_test_function(*(list.begin()))] (const double& a, const double& b) mutable
{
double current_value = semi_expensive_test_function(b);
if(current_value < current_min_value)
{
current_min_value = std::move(current_value);
return true;
}
return false;
});
}
使用有状态的lambdas似乎是一条出路。问题是:有没有一种代码更紧凑的方法来实现这一点?好吧,假设Boost像现在的标准库一样,您可以使用以下方法:
#include <boost/range/adaptor/transformed.hpp>
#include <algorithm>
int main()
{
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto abs_list = list | boost::adaptors::transformed(+[](int v) { return std::abs(v); });
// ^ - read http://stackoverflow.com/questions/11872558/using-boost-adaptors-with-c11-lambdas
auto it = std::min_element(abs_list.begin(), abs_list.end(), std::less<int>{});
std::cout << *it;
}
#包括
#包括
int main()
{
向量列表={-2,-1,6,8,10};
自动abs_list=list | boost::adapters::transformed(+[](intv){返回std::abs(v);});
//^-阅读http://stackoverflow.com/questions/11872558/using-boost-adaptors-with-c11-lambdas
auto it=std::min\u元素(abs\u list.begin(),abs\u list.end(),std::less{});
std::cout使用,它将类似于:
ranges::min(list, std::less<>{}, [](auto e) { return std::abs(e); });
ranges::min(列表,std::less{},[](自动e){返回std::abs(e);});
如果它能被重用,并给您另一个选择,您可以按照std约定编写自己的通用算法
template <typename T, typename ForwardIt, typename UnaryFunction, typename Comparator>
ForwardIt find_min_return_value(ForwardIt first, ForwardIt last, UnaryFunction op, Comparator compare)
{
if (first == last)
return last;
ForwardIt smallestItr = first;
T smallestValue = op(*first);
for (auto itr = first + 1; itr != last; ++itr)
{
T current = op(*itr);
if (compare(current, smallestValue))
{
smallestValue = current;
smallestItr = itr;
}
}
return smallestItr;
}
模板
ForwardIt find_min_return_值(ForwardIt first、ForwardIt last、UnaryFunction op、Comparator compare)
{
如果(第一个==最后一个)
最后返回;
ForwardIt smallestr=第一个;
T最小值=op(*第一);
用于(自动itr=第一个+1;itr!=最后一个;++itr)
{
T电流=op(*itr);
if(比较(当前值、最小值))
{
最小值=电流;
smallestr=itr;
}
}
返回smallestr;
}
然后,使用非常紧凑的代码,每个元素只执行一次操作:
int main()
{
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto it1 = find_min_return_value<int>(list.begin(), list.end(), [](int i){ return std::abs(i); }, std::less<int>());
std::vector<std::string> strings = { "Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit" };
auto it3 = find_min_return_value<size_t>(strings.begin(), strings.end(), [](std::string s){ return s.length(); }, std::less<size_t>());
std::cout << *it1 << "\n"; // outputs -1
std::cout << *it3 << "\n"; // outputs sit
}
intmain()
{
向量列表={-2,-1,6,8,10};
auto it1=find_min_return_value(list.begin(),list.end(),[](int i){return std::abs(i);},std::less());
向量字符串={“Lorem”、“ipsum”、“dolor”、“sit”、“amet”、“Concertetur”、“Adipising”、“elit”};
auto it3=find_min_return_value(strings.begin(),strings.end(),[](std::string s){return s.length();},std::less());
std::cout取决于时间复杂度,如果没有时间复杂度约束,则可以使用std::sort(list.begin(),list.end())第一个元素是最小值,最大值是使用默认比较器的最后一个元素,即nlogn。std::min\u元素
?std::minmax\u元素
,或std::minmax\u元素
,如果需要both@AdamHunyadistd::minmax_元素(list.begin(),list.end(),[](int a,int b){return std::abs(a)
@XinHuang列表很长,所以我不想复制它。另外,我想为每个元素调用一次其最小返回值的函数。嗯,这很好,但我的列表占用了大量内存,所以我不想复制它:我的解决方案根本不复制。boost::adapters::transformed
唯一的视图。确实做到了:DsmallestValue=current;
可以是smallestValue=std::move(current);
,op
可以在投影时重命名为project
(该命名在范围库中使用)。
ranges::min(list, std::less<>{}, [](auto e) { return std::abs(e); });
template <typename T, typename ForwardIt, typename UnaryFunction, typename Comparator>
ForwardIt find_min_return_value(ForwardIt first, ForwardIt last, UnaryFunction op, Comparator compare)
{
if (first == last)
return last;
ForwardIt smallestItr = first;
T smallestValue = op(*first);
for (auto itr = first + 1; itr != last; ++itr)
{
T current = op(*itr);
if (compare(current, smallestValue))
{
smallestValue = current;
smallestItr = itr;
}
}
return smallestItr;
}
int main()
{
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto it1 = find_min_return_value<int>(list.begin(), list.end(), [](int i){ return std::abs(i); }, std::less<int>());
std::vector<std::string> strings = { "Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit" };
auto it3 = find_min_return_value<size_t>(strings.begin(), strings.end(), [](std::string s){ return s.length(); }, std::less<size_t>());
std::cout << *it1 << "\n"; // outputs -1
std::cout << *it3 << "\n"; // outputs sit
}