Getting min_element of from a vector of structs based on two variables

std::min_element
c index of smallest element in vector
remove element from vector c++
std::min
max_element c++
std::minmax_element
c++ vector max element index
std::min_element lambda

So I have a vector of structs that is defined and used in the following manner:

enum ID {
    alpha,
    beta,
    gamma
};

using TimePoint = std::chrono::time_point<std::chrono::system_clock>;

typedef struct pInfo {
    int bar;
    int key;
    ID id;
    TimePoint tPoint;
} pInfo;

std::vector<pInfo> pMembers;

I would like to basically iterate through this vector after populating it with all the items and get a reference to the matching element that meets my criteria.

The criteria is that I would have a function that passes in a type of ID, and it will return a reference to the vector element that is the best fit which means the one with the lowest TimePoint.

So for reference the function would be something like: pInfo& getNext(ID p_id);

And if I have a vector that has a few elements of each, like 4 alpha, 4 gamma, 4 beta I want the function to only check the ones with ID == alpha if that's what I pass in.

Right now I was using something like this:

std::min_element(std::begin(pMembers), std::end(pMembers), [](auto&& lhs, auto&& rhs){return lhs.tPoint < rhs.tPoint};

But this doesn't account for me wanting to only get certain types.

How would I do something like this?

Make the lambda capture the passed ID so it can be used in the comparisons, eg:

pInfo& getNext(ID p_id)
{
    if (pMembers.empty())
        throw ...; // nothing to search, can't return a reference to nothing, so throw an exception instead...

    auto iter = std::min_element(std::begin(pMembers), std::end(pMembers),
        [=](const pInfo &lhs, const pInfo &rhs)
        {
            if (lhs.id == p_id) {
                if (rhs.id != p_id) return true;
            }
            else if (rhs.id == p_id) {
                if (lhs.id != p_id) return false;
            }
            else {
                return false;
            }
            return lhs.tPoint < rhs.tPoint;
        }
    );

    if (iter->id != p_id)
        throw ...; // p_id not found, can't return a reference to nothing, so throw an exception instead...

    return *iter;
}

Alternatively, try something more like this:

pInfo& getNext(ID p_id)
{
    std::vector<std::reference_wrapper<pInfo>> v;

    std::copy_if(std::begin(pMembers), std::end(pMembers), std::back_inserter(v),
        [=](const pInfo &item){ return item.id == p_id; }
    );
    if (v.empty())
        throw ...; // p_id not found, can't return a reference to nothing, so throw an exception instead...

    auto iter = std::min_element(std::begin(v), std::end(v),
        [](const pInfo &lhs, const pInfo &rhs){ return lhs.tPoint < rhs.tPoint; }
    );
    return *iter;
}

std::min_element in C++, std::min_element is defined inside the header file <algorithm> and it returns an iterator pointing to Finding the minimum value between the third and the 2; For comparison based on a pre-defined function: Syntax: template Implementation of lower_bound() and upper_bound() in Vector of Pairs in C++� For comparison based on a pre-defined function: Syntax: template ForwardIterator min_element (ForwardIterator first, ForwardIterator last, Compare comp); Here, first and last are the same as previous case. comp: Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned

I would just store the objects with different IDs in different vectors, one vector for each ID:

std::map<ID, std::vector<pInfo>> pMembers;

If you can't or won't do that, then I'd use a filtering iterator adaptor. The following example uses Boost.Iterator:

auto const filter = [p_id](auto const& id) { return id == p_id; };
auto const compare = [](auto const& a, auto const& b) { return a.tPoint < b.tPoint; };

auto const it = std::min_element(boost::make_filter_iterator(filter, begin(pMembers), end(pMembers)),
                                 boost::make_filter_iterator(filter,   end(pMembers), end(pMembers)),
                                 compare).base();

Expanding on Remy's answer, this is how I would write their first way of doing it:

auto const it = std::min_element(begin(pMembers), end(pMembers), [=](auto const& a, auto const& b)
{
    return std::forward_as_tuple(a.id != p_id, a.tPoint)
         < std::forward_as_tuple(b.id != p_id, b.tPoint);
});

How to find the minimum and maximum element of a Vector using , of Vector using *min_element() in STL Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price� In this article we will discuss different techniques to get an element from vector by index or position. In vector elements are indexed from 0 to size() – 1. To access any element in vector by index vector provides two member functions i.e. at() operator[] Let’s discuss them in detail, Access an element in vector using operator []

You can also simply apply the range-based-for to this problem as follows:

DEMO

const pInfo& getNext(const std::vector<pInfo>& pMembers, ID p_id)
{
    const pInfo* p{nullptr};
    TimePoint min{TimePoint::max()};

    for(const auto& p_i : pMembers)
    {
        if(p_i.id == p_id && p_i.tPoint < min)
        {
            min = p_i.tPoint;
            p = &p_i;
        }
    }

    if(!p){
        throw std::runtime_error("no data.");
    }

    return *p;
}

std::min_element, 2 3 4 5 6 7 8 9 10 11, template < class ForwardIterator> ForwardIterator std:: min_element, std::max_element bool myfn( int i, int j) { return i<j; } struct myclass� Returns an iterator pointing to the element with the smallest value in the range [first,last). The comparisons are performed using either operator< for the first version, or comp for the second; An element is the smallest if no other element compares less than it.

std::min_element, std::min_element (2), (since C++17) and must be able to accept all values of type (possibly const) Type1 and Type2 regardless 1, 4, 1, 5, 9}; std::vector<int> ::iterator result = std::min_element(v.begin(), v.end()); std::cout� first, last - forward iterators defining the range to examine policy - the execution policy to use. See execution policy for details.: comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns true if a is less than b.

max_element to a vector of structs (vector<myStruct>)?, But what if the elements of the vector are structs and we want to find only (or else the last element does not get compared): vector<int>::iterator last the order by multiple values each having a particular priority; you would,� // of Vector using *min_element() in STL Query to find the maximum and minimum weight between two nodes in the given tree using LCA. Based on 2 vote(s)

C++, in a vector, you can use the methods std::max_element and std::min_element v = {5, 2, 8, 10, 9}; int maxElementIndex = std::max_element(v.begin(),v.end())� The vector present contains the pointers to this structure. Pointers to this structure are added in some other functions. Now, I want to write a function to display the contents of the structure of the vector. Please suggest how to do that.

Comments
  • And the last line of returning iter->get(); throws an error.