0

I have a data structure like this:

struct Speed {

       int set; //set by user
       int act; //actual speed
       int millis; //millis since epoch
}

vector<Speed> data;

Now I want to draw this vector. To create a nice axis, I want to find the max and min of data in this vector. I do like this but obviously, since it is based only on set, it will fail me if at any point act is smaller or larger than set. I mean the Y axis of the chart should be between minimum of set, act and maximum of 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?
});

**I KNOW ** how to write a normal code not involving algorithm and lambdas to achieve the result...but I am interested to see how it is possible to do with algorithm/lambda WITHOUT having operator overloading in the structure.

I could also do the same for act then compare results...but that would cost me 4 loops!

11
  • 1
    It's unclear how you want the comparison to act? You want the smallest/largest of set and act? The average? The min/max of the sum of set and act? There are a lot of ways to compare two values. Commented Oct 9, 2017 at 15:47
  • @Jonesinator I just want to get min and max for my chart to cover both values ranges Commented Oct 9, 2017 at 15:48
  • Is your question about constructing a comparison function for two properties (set , act) ? Commented Oct 9, 2017 at 15:54
  • Do you want the min/max elements w.r.t set and also the min/max elements w.r.t act, or the min/max elements w.r.t to both set and act? Commented Oct 9, 2017 at 15:57
  • @Daniel w.r.t both of course! Commented Oct 9, 2017 at 15:57

2 Answers 2

2

Generally, I would recommend most readable code.

Thus, it would be something like (assuming at least one item):

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

However, if the data is really big or the logic is more complex, I would recommend to have an object that accumulate statistics and do some kind of loop over the data.

Sign up to request clarification or add additional context in comments.

1 Comment

I indeed ended up using my own loop because otherwise I would possibly get 2x the calls to get a value (with two shared pointers) instead of one in my loop. Small optimization, but over time, that's still quite a bit of cycles saved.
2

You can use std::min and std::max inside of your std::min_element and std::max_element invocations.

#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";
}

A single pass with std::minmax can't really work here. Each comparison of elements must return a boolean where true means the left-hand side is less-than the right-hand side and false means the the left-hand side is greater-than or equal-to the right-hand side (i.e. a strict weak ordering is required). However, here a single element can both be less-than and greater-than another element. You could easily write your own function to make a single-pass minmax_element, but I don't think it fits nicely into the existing STL functions without making two passes.

5 Comments

If this is what OP wants as a result, then I would use std::minmax_element for each members then afterward get final minimum and maximum. Probably easier to read and more efficient.
With some changes onlinegdb.com/SJZCyXKhb it is close to what I meant...but would be nice if this can be done in only one loop
I think that the one loop approach won't properly handle all cases. For example, would it works if the same item is both the minimum for one field and the maximum for the other field.
Yeah, actually @Phil1970 is right, the std::minmax_element implementation doesn't work for all cases.
yep it failed for some cases!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.