22

How can I get the minimum or maximum element in a vector of structures in C++, based on some field in the structure?

For example:

struct Size {
    int width, height;
};
vector<Size> sizes;

And now I want to solve that based on width and create a new vector for that. And then sort based on height and create a new vector for that.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user2381422
  • 5,645
  • 14
  • 42
  • 56

5 Answers5

21

In C++11, you can use the std::minmax_element() standard function, which (given a pair of iterators) and possibly a custom comparator (that would allow you to define the field on which the ordering is based), will return you an iterator to the minimum and an iterator to the maximum element, packed in an std::pair.

So for instance:

#include <algorithm> // For std::minmax_element
#include <tuple> // For std::tie
#include <vector> // For std::vector
#include <iterator> // For global begin() and end()

std::vector<Size> sizes = { {4, 1}, {2, 3}, {1, 2} };

decltype(sizes)::iterator minEl, maxEl;
std::tie(minEl, maxEl) = std::minmax_element(begin(sizes), end(sizes),
    [] (Size const& s1, Size const& s2)
    {
        return s1.width < s2.width;
    });

Here is a live example.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
20

You can use std::min_element and std::max_element with a suitable functor:

bool cmp(const Size& lhs, const Size& rhs)
{
  return lhs.width < rhs.width;
}

then

auto min_it = std::min_element(sizes.begin(), sizes.end(), cmp);
auto max_it = std::max_element(sizes.begin(), sizes.end(), cmp);

In C++11 you can replace cmp with a lambda expression.

See also: std::minmax_element

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
11
vector<Size> sizes;
...
vector<Size> sortedByWidths(sizes);
vector<Size> sortedByHeights(sizes);
sort(sortedByWidths.begin(), sortedByWidths.end(), 
    [](Size s1, Size s2) {return s1.width < s2.width;});
sort(sortedByHeights.begin(), sortedByHeights.end(), 
    [](Size s1, Size s2) {return s1.height< s2.height;});
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
4

Solution using std::minmax_element with lambda expression:

#include <iostream>
#include <vector>

struct Size {
    int width, height;
};

int main()
{
     std::vector<Size> sizes;

     sizes.push_back({4,1});
     sizes.push_back({2,3});
     sizes.push_back({1,2});

     auto minmax_widths = std::minmax_element(sizes.begin(), sizes.end(),
         [] (Size const& lhs, Size const& rhs) {return lhs.width < rhs.width;});
     auto minmax_heights = std::minmax_element(sizes.begin(), sizes.end(),
         [] (Size const& lhs, Size const& rhs) {return lhs.height < rhs.height;});

     std::cout << "Minimum (based on width): " << minmax_widths.first->width << std::endl;
     std::cout << "Maximum (based on width): " << minmax_widths.second->width << std::endl;

     std::cout << "Minimum (based on height): " << minmax_heights.first->height << std::endl;
     std::cout << "Maximum (based on height): " << minmax_heights.second->height << std::endl;
}
Dan
  • 1,729
  • 18
  • 11
2

Use std::min/std::max/std::minmax _element with comparator. http://en.cppreference.com/w/cpp/algorithm/min_element

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • What do you mean by "with comparator"? Can you elaborate in your answer (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today)? – Peter Mortensen Jul 13 '21 at 21:43
  • @PeterMortensen, Well, comparator is actually usable slang (it's actually comparision function in std). From cppref (I have link to it in answer): comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if a is less than b. And no, answer should not appear as it was written today, just cause it was written in 2013. – ForEveR Jul 14 '21 at 22:49