C++ 查找在一个范围内产生最大输出的元素的标准函数?
为了提高代码的可读性,我正试图摆脱重新发明轮子的习惯 问题: 有时我有一个简单的数据范围和一个相关的函数,比如Foo,我想最大化输出。假设我们处理的是int,这里根本没有处理任何数组,而Foo函数是这样的,我们需要尝试每个输入 例子: 范围:[5,8 我们想做一个返回6的函数 自定义解决方案: 问题: 我经常使用这个函数,所以我认为应该有一种STL方法来实现它。有吗 注: 上面的解决方案比强迫用户只为了找到一个数字而构建一个数组快大约100倍——想想所有无意义的缓存未命中!您可以使用中定义的std::max\u元素 可以使用中定义的std::max\u元素C++ 查找在一个范围内产生最大输出的元素的标准函数?,c++,stl,C++,Stl,为了提高代码的可读性,我正试图摆脱重新发明轮子的习惯 问题: 有时我有一个简单的数据范围和一个相关的函数,比如Foo,我想最大化输出。假设我们处理的是int,这里根本没有处理任何数组,而Foo函数是这样的,我们需要尝试每个输入 例子: 范围:[5,8 我们想做一个返回6的函数 自定义解决方案: 问题: 我经常使用这个函数,所以我认为应该有一种STL方法来实现它。有吗 注: 上面的解决方案比强迫用户只为了找到一个数字而构建一个数组快大约100倍——想想所有无意义的缓存未命中!您可以使用中定义的st
一般来说,STL中的算法处理由迭代器遍历的值序列。它们也倾向于返回迭代器。这就是它使用的模式 如果你正在做很多类似的事情,其中你的输入序列是一个连续的数字列表,那么你需要一个迭代器,在序列上进行迭代,而不需要任何存储 出现了一点搜索,看起来它可以做你想要的。我相信还有其他类似的 警告-完全未测试的代码
auto iter = std::max_element(boost::counting_iterator<int>(5),
boost::counting_iterator<int>(8),
// a comparator that compares two elements
);
return *iter; // should be '6'
一般来说,STL中的算法处理由迭代器遍历的值序列。它们也倾向于返回迭代器。这就是它使用的模式 如果你正在做很多类似的事情,其中你的输入序列是一个连续的数字列表,那么你需要一个迭代器,在序列上进行迭代,而不需要任何存储 出现了一点搜索,看起来它可以做你想要的。我相信还有其他类似的 警告-完全未测试的代码
auto iter = std::max_element(boost::counting_iterator<int>(5),
boost::counting_iterator<int>(8),
// a comparator that compares two elements
);
return *iter; // should be '6'
正如其他人所观察到的,定义std::max_元素是为了获得一个范围内的最大元素
在您的例子中,迭代器是一个整数,而取消引用该迭代器的结果是…一些明显与输入无关的结果,但显然您有一些方法可以有效地获得它
在这种情况下,我可能会定义一个专门的迭代器类,然后将其与std::max_元素一起使用:
包括
包括
包括
//你的联想功能在这里,我刚刚做了些事情
//输入与输出之间的关系不一定是
//一目了然
int关联函数int输入{
INTA=输入*65537+17;
int b=a*a*a;
返回b%127;
}
类迭代器{
int值;
公众:
//从int值创建迭代器
显式yourIteratorint值:valuevalue{}
//迭代器获取关联的值
int运算符*const{return association_functionvalue;}
//前进到下一个值:
迭代运算符++int{
迭代器值;
++价值观;
返回温度;
}
您的迭代器和运算符++{
++价值观;
归还*这个;
}
//与另一个迭代器比较
布尔运算符==yourIterator常量和其他常量{返回值==other.value;}
布尔运算符!=yourIterator常量和其他常量{返回值!=other.value;}
//获取当前迭代器的索引:
显式运算符int const{return value;}
};
int main{
//对于演示,打印出特定范围内的所有值:
std::cout正如其他人所观察到的,定义std::max_元素是为了获得一个范围内的最大元素
在您的例子中,迭代器是一个整数,而取消引用该迭代器的结果是…一些明显与输入无关的结果,但显然您有一些方法可以有效地获得它
在这种情况下,我可能会定义一个专门的迭代器类,然后将其与std::max_元素一起使用:
包括
包括
包括
//你的联想功能在这里,我刚刚做了些事情
//输入与输出之间的关系不一定是
//一目了然
int关联函数int输入{
INTA=输入*65537+17;
int b=a*a*a;
返回b%127;
}
类迭代器{
int值;
公众:
//从int值创建迭代器
显式yourIteratorint值:valuevalue{}
//迭代器获取关联的值
int运算符*const{return association_functionvalue;}
//前进到下一个值:
迭代运算符++int{
迭代器值;
++价值观;
返回温度;
}
您的迭代器和运算符++{
++价值观;
归还*这个;
}
//与另一个迭代器比较
布尔运算符==yourIterator常量和other常量{返回值==other。
值;}
接线员=yourIterator常量&other常量{返回值!=other.value;}
//获取当前迭代器的索引:
显式运算符int const{return value;}
};
int main{
//对于演示,打印出特定范围内的所有值:
std::coutC++20范围可以做到这一点: 样板 T argmax_iotaT begin、T end、F&&score{//真的想不出一个好名字;也许它甚至不应该拥有自己的功能 返回std::ranges::maxstd::views::iotabegin,end,std::less{},std::refscore; //超过[开始,结束]范围内的值,通过计算iota。。。 //找到产生最大值的最大值。。。 //当传递到投影函数得分时。。。 //使用std::less诱导的顺序下的值 }
iota不会将整个范围存储在任何位置。范围中的迭代器包含一个T值,当迭代器增加时,该值会增加。C++20范围可以做到这一点: 样板 T argmax_iotaT begin、T end、F&&score{//真的想不出一个好名字;也许它甚至不应该拥有自己的功能 返回std::ranges::maxstd::views::iotabegin,end,std::less{},std::refscore; //超过[开始,结束]范围内的值,通过计算iota。。。 //找到产生最大值的最大值。。。 //当传递到投影函数得分时。。。 //使用std::less诱导的顺序下的值 }
iota不会将整个范围存储在任何位置。范围中的迭代器包含一个T值,当迭代器增加时,该值会增加。感谢您的快速响应,但这不是一回事。它太低效了。@Elliott:不确定它是如何低效的;它缺少您请求的键控操作,因此不是complete回答,但它非常有效。@Elliott您能详细说明一下吗?您的代码片段基本上对范围内的元素进行线性扫描,这就是max_元素所做的too@Elliott需要max_元素的重载,它需要一个比较器,并将他的LhsMoreThanRhs传递到那里。@Eugene,对于大范围,比如说0到40000,这将是about速度慢100倍。因此,即使它使我的代码更具可读性,这也不是一个值得选择的选项。感谢您的快速响应,但这不是同一件事。它太低效了。@Elliott:不确定它是如何低效的;它缺少您请求的键控操作,因此它不是一个完整的答案,但它非常高效。@Elliott可以告诉您您的代码片段本质上是对范围内的元素进行线性扫描,这是max_元素所做的too@Elliott需要一个比较器的max_元素的过载,并将他的LhsMoreThanRhs传递到那里。@Eugene,对于大范围,比如说0到40000,这将慢大约100倍。所以这根本不是一个值得的选择,ev恩,如果它能让我的代码更具可读性。你所拥有的已经足够了。所以我只是建议万一有问题。对我来说,你提供的内容足够简洁,所以类似的东西是一个选项?@onyanbu,也许除了关于不重新发明轮子的部分。我不确定OP对添加一个小型自定义迭代器以与max_el一起使用有何想法不,你不需要一个容器。看看我的例子。@TedLyngmo,嗯。我明白了。对不起,我完全错过了。你所拥有的已经足够了。所以我只是在有问题的情况下建议。对我来说,你提供的很简洁。好吧,那么类似的东西是一个选择吗?@Onyanbu,也许除了关于不重新发明轮子的部分。我“我不确定OP对添加一个小的自定义迭代器以与max_元素一起使用有何想法。@Onyanbu不,您不需要容器。检查我的示例。@TedLyngmo-huh。我明白了。对不起,我完全错过了。太好了!我只会将b从int更改为long,因为a*a*a可能会导致溢出。@RonaldSouza:该函数只是一个占位符,所以我们可以使用它。”ll不是很相关。很好!我只会将b从int改为long,因为a*a*a可能会导致溢出。@RonaldSouza:那个函数只是一个占位符,所以它工作得很好并不是真的相关。这就是我在制作自己的计数迭代器时想要的。这就是我在制作自己的计数迭代器时想要的。
std::vector<int> v{ 3, 1, -14, 1, 5, 9 };
std::vector<int>::iterator result;
result = std::max_element(v.begin(), v.end());
std::cout << "max element at: " << std::distance(v.begin(), result) << '\n';
auto iter = std::max_element(boost::counting_iterator<int>(5),
boost::counting_iterator<int>(8),
// a comparator that compares two elements
);
return *iter; // should be '6'
values in range: 64 90 105 60 33
Largest element: 105
index of largest element: 7