【问题标题】:Finding maximum and minimum in vector of custom data using algorithm使用算法在自定义数据向量中查找最大值和最小值
【发布时间】:2017-10-10 01:33:35
【问题描述】:

我有这样的数据结构:

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 个循环!

【问题讨论】:

  • 不清楚您希望比较如何进行?你想要最小/最大的场景和行为吗?平均值?集合和行为之和的最小值/最大值?有很多方法可以比较两个值。
  • @Jonesinator 我只想让图表的最小值和最大值涵盖两个值范围
  • 您的问题是关于为两个属性(set、act)构建比较函数吗?
  • 您想要设置最小/最大元素 w.r.t 以及最小/最大元素 w.r.t 动作,还是最小/最大元素 w.r.t 同时设置 动作?跨度>
  • @Daniel w.r.t 当然!

标签: c++ c++11 stl-algorithm


【解决方案1】:

一般来说,我会推荐最易读的代码。

因此,它会类似于(假设至少有一项):

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);

但是,如果数据真的很大或者逻辑更复杂,我建议有一个对象来积累统计数据并对数据进行某种循环。

【讨论】:

  • 我确实最终使用了自己的循环,因为否则我可能会获得 2 倍的调用来获取一个值(带有两个共享指针),而不是循环中的一个。小幅优化,但随着时间的推移,这仍然节省了相当多的周期。
【解决方案2】:

您可以在 std::min_elementstd::max_element 调用中使用 std::minstd::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 的单次传递在这里实际上无法正常工作。元素的每次比较都必须返回一个布尔值,其中true 表示左侧小于右侧,false 表示左侧大于或等于右侧边(即需要严格的弱排序)。但是,这里单个元素既可以小于 也可以 大于另一个元素。您可以轻松编写自己的函数来制作单遍 minmax_element,但我认为如果不执行两遍,它就不能很好地融入现有的 STL 函数。

【讨论】:

  • 如果这是 OP 想要的结果,那么我将为每个成员使用 std::minmax_element,然后获得最终的最小值和最大值。可能更易于阅读且效率更高。
  • 有一些变化onlinegdb.com/SJZCyXKhb 接近我的意思...但是如果这可以在一个循环中完成会很好
  • 我认为单循环方法不能正确处理所有情况。例如,如果同一项目既是一个字段的最小值,又是另一个字段的最大值,它会起作用吗?
  • 是的,实际上@Phil1970 是对的,std::minmax_element 的实现并不适用于所有情况。
  • 是的,在某些情况下它失败了!
猜你喜欢
  • 2015-10-11
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
  • 2018-05-03
  • 1970-01-01
  • 2019-06-08
相关资源
最近更新 更多