0

I have a struct that has a member called id.

struct st
{
    int id;
    double d;
};

st s1 = {1, 5.6};
st s2 = {2, 5.7};
st s3 = {3, 4.3};

vector<st> vec;
vec.push_back(s1);
vec.push_back(s2);
vec.push_back(s3);

int max = 0;
for(int i=0; i < vec.size(); i++)
{
    if(vec[i].id > max)
        max = vec[i].id;
}

How can I find the maximum id in the vector of these structs without the use of for loop? I saw this answer but did not understand. Is there a more efficient way using *max_element?

walnut
  • 21,629
  • 4
  • 23
  • 59
Hadi GhahremanNezhad
  • 2,377
  • 5
  • 29
  • 58
  • 1
    Does this answer your question? [Finding max\_element of a vector where a member is used to decide if its the maximum](https://stackoverflow.com/questions/3994890/finding-max-element-of-a-vector-where-a-member-is-used-to-decide-if-its-the-maxi) or [How to get min or max element in a vector of objects in c++, based on some field of the object?](https://stackoverflow.com/questions/26766136/how-to-get-min-or-max-element-in-a-vector-of-objects-in-c-based-on-some-field) – walnut Feb 11 '20 at 19:43
  • @Hadi GhahremanNezhad You can not find the maximum element without a loop. The standard algorithm std::max_element is in fact a loop.:) L Otherwise for a small vector you can use if-else statements. – Vlad from Moscow Feb 11 '20 at 19:43
  • Unless your vector's elements meet certain conditions, the most efficient way is going to involve a loop. If you really need a better way, then you could sort the elements and then just pick the last one. – Etienne de Martel Feb 11 '20 at 19:45
  • @walnut yes, [this answer](https://stackoverflow.com/a/3995006/6129428) helps, but the one below by idclev is more complete. – Hadi GhahremanNezhad Feb 11 '20 at 19:54
  • @walnut oh didnt realize, – 463035818_is_not_an_ai Feb 11 '20 at 20:02

1 Answers1

6

The answer you link is about searching a vector for an element that meets a given criterion. Finding the maximum is different, because you have to consider all elements before you know the maximum element.

std::max_element lets you choose a comparison, so you can compare only for id easily:

auto max = *std::max_element(vec.begin(),
                             vec.end(),
                             [](const st& a,const st& b) { return a.id < b.id; });                 

You mentioned *max_element, hence I suppose that you are aware that it returns an iterator that you can dereference. However, be aware that if the container is empty the above will break (undefined behavior due to dereferencing the end iterator) and the safer way is:

auto it = std::max_element(vec.begin(),
                             vec.end(),
                             [](const st& a,const st& b) { return a.id < b.id; });                 
if (it == vec.end()) throw "max_element called on emtpy vector";
auto max = *it;

PS

[...] without the use of for loop?

Do not confuse using algorithms with "no loops". The link above has a possible implementation and if you study it you will notice that it isnt magic, but just a plain loop. The advantage of the alogrithm is expressiveness and less possibilities for mistakes.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185