使用算法查找自定义数据向量中的最大值和最小值
Finding maximum and minimum in vector of custom data using algorithm
我有这样的数据结构:
struct Speed {
int set; //set by user
int act; //actual speed
int millis; //millis since epoch
}
vector<Speed> data;
现在我想画这个矢量图。为了创建一个漂亮的轴,我想找到这个向量中数据的最大值和最小值。我确实喜欢这个,但显然,因为它仅基于 set
,所以如果 act
小于或大于 set
,我就会失败。我的意思是图表的 Y
轴应该介于 set, act
的最小值和 set, act
的最大值之间。
auto max = std::max_element(begin(data), end(data),
[&](const Speed& a, const Speed& b){
return a.set() < b.set();
//how about act?
});
auto min = std::min_element(begin(data), end(data),
[&](const Speed& a, const Speed& b){
return a.set() < b.set();
//how about act?
});
**我知道**如何编写不涉及算法和 lambda 的普通代码来实现结果...但我很想知道如何在没有运算符的情况下使用 algorithm/lambda结构重载。
我也可以对 act
做同样的事情,然后比较结果……但这会花费我 4 个循环!
您可以在 std::min_element
和 std::max_element
调用中使用 std::min
和 std::max
。
#include <algorithm>
#include <iostream>
#include <vector>
struct Speed {
int set;
int act;
int millis;
};
int main() {
std::vector<Speed> data = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
auto max_val = std::max_element(begin(data), end(data),
[](const Speed& a, const Speed& b){
return std::max(a.set, a.act) < std::max(b.set, b.act);
});
auto min_val = std::min_element(begin(data), end(data),
[](const Speed& a, const Speed& b){
return std::min(a.set, a.act) < std::min(b.set, b.act);
});
std::cout << "MAX: " << max_val->set << " " << max_val->act << "\n";
std::cout << "MIN: " << min_val->set << " " << min_val->act << "\n";
}
std::minmax
的单次传递在这里真的行不通。元素的每个比较必须 return 一个布尔值,其中 true
表示左侧小于右侧,false
表示左侧大于或等于右侧(即需要严格的弱排序)。但是,这里单个元素可以同时小于 和 大于另一个元素。您可以轻松编写自己的函数来进行单次传递 minmax_element,但我认为如果不进行两次传递,它就不太适合现有的 STL 函数。
一般来说,我会推荐最易读的代码。
因此,它类似于(假设至少有一项):
auto set_minmax = std::minmax_element(begin(data), end(data),
[&](const Speed& a, const Speed& b) { return a.set < b.set; });
auto act_minmax = std::minmax_element(begin(data), end(data),
[&](const Speed& a, const Speed& b) { return a.act < b.act; });
auto min_act_set = std::min(*set_minmax.first, *act_minmax.first);
auto max_act_set = std::max(*set_minmax.second, *act_minmax.second);
但是,如果数据真的很大或者逻辑比较复杂,我会建议有一个对象来累积统计数据并对数据进行某种循环。
我有这样的数据结构:
struct Speed {
int set; //set by user
int act; //actual speed
int millis; //millis since epoch
}
vector<Speed> data;
现在我想画这个矢量图。为了创建一个漂亮的轴,我想找到这个向量中数据的最大值和最小值。我确实喜欢这个,但显然,因为它仅基于 set
,所以如果 act
小于或大于 set
,我就会失败。我的意思是图表的 Y
轴应该介于 set, act
的最小值和 set, act
的最大值之间。
auto max = std::max_element(begin(data), end(data),
[&](const Speed& a, const Speed& b){
return a.set() < b.set();
//how about act?
});
auto min = std::min_element(begin(data), end(data),
[&](const Speed& a, const Speed& b){
return a.set() < b.set();
//how about act?
});
**我知道**如何编写不涉及算法和 lambda 的普通代码来实现结果...但我很想知道如何在没有运算符的情况下使用 algorithm/lambda结构重载。
我也可以对 act
做同样的事情,然后比较结果……但这会花费我 4 个循环!
您可以在 std::min_element
和 std::max_element
调用中使用 std::min
和 std::max
。
#include <algorithm>
#include <iostream>
#include <vector>
struct Speed {
int set;
int act;
int millis;
};
int main() {
std::vector<Speed> data = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
auto max_val = std::max_element(begin(data), end(data),
[](const Speed& a, const Speed& b){
return std::max(a.set, a.act) < std::max(b.set, b.act);
});
auto min_val = std::min_element(begin(data), end(data),
[](const Speed& a, const Speed& b){
return std::min(a.set, a.act) < std::min(b.set, b.act);
});
std::cout << "MAX: " << max_val->set << " " << max_val->act << "\n";
std::cout << "MIN: " << min_val->set << " " << min_val->act << "\n";
}
std::minmax
的单次传递在这里真的行不通。元素的每个比较必须 return 一个布尔值,其中 true
表示左侧小于右侧,false
表示左侧大于或等于右侧(即需要严格的弱排序)。但是,这里单个元素可以同时小于 和 大于另一个元素。您可以轻松编写自己的函数来进行单次传递 minmax_element,但我认为如果不进行两次传递,它就不太适合现有的 STL 函数。
一般来说,我会推荐最易读的代码。
因此,它类似于(假设至少有一项):
auto set_minmax = std::minmax_element(begin(data), end(data),
[&](const Speed& a, const Speed& b) { return a.set < b.set; });
auto act_minmax = std::minmax_element(begin(data), end(data),
[&](const Speed& a, const Speed& b) { return a.act < b.act; });
auto min_act_set = std::min(*set_minmax.first, *act_minmax.first);
auto max_act_set = std::max(*set_minmax.second, *act_minmax.second);
但是,如果数据真的很大或者逻辑比较复杂,我会建议有一个对象来累积统计数据并对数据进行某种循环。