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@AdamHunyadi
std::minmax_元素(list.begin(),list.end(),[](int a,int b){return std::abs(a)
@XinHuang列表很长,所以我不想复制它。另外,我想为每个元素调用一次其最小返回值的函数。嗯,这很好,但我的列表占用了大量内存,所以我不想复制它:我的解决方案根本不复制。
boost::adapters::transformed
唯一的视图。确实做到了:D
smallestValue=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
}