HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Find element yielding the largest value w.r.t. custom function

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
theyieldingfunctionvaluelargestcustomelementfind

Problem

I made a function to find the element that yields the largest value when put into a custom functor.

I think this is missing from the STL. I can think of three ways to do this in STL:

  • Transform the container by the functor. Find the maximum in the transformed version. Take the corresponding element from the original container.



  • Transform the container to an iterable of std::pairs containing the iterators to the original values and the corresponding functor result value. Write a custom comparison function which compares the .second of the pairs. Find max among the pairs with std::max_element. Take .first of the resulting iterator.



  • Use a custom comparator functor in std::max_element (`return f(lhs)



The first two are really cumbersome and the third calls the functor twice as many times as necessary. Hence this:

template
auto maxElementBy(Iterable const& iterable, UnaryFun criterion)
    -> decltype(std::begin(iterable))
{
    typedef decltype(criterion(*std::begin(iterable))) CriterionResult;

    auto itCurrent = std::begin(iterable);
    auto itEnd = std::end(iterable);

    if (itCurrent == itEnd)
    {
        return itEnd;
    }

    CriterionResult bestValue = criterion(*itCurrent);
    auto itBest = itCurrent;
    ++itCurrent;

    for (; itCurrent != itEnd; ++itCurrent)
    {
        CriterionResult currentValue = criterion(*itCurrent);
        if (bestValue < currentValue)
        {
            itBest = itCurrent;
            bestValue = std::move(currentValue);
        }
    }
    return itBest;
}


Any suggestions?

Solution

Setting aside the std::accumulate discussion, I have one recommendation. The signature

template
auto maxElementBy(Iterator first, Iterator last, UnaryFun criterion)
    -> Iterator


seems to be more flexible. It allows partial ranges, and seems more in line with the std design approach.

Code Snippets

template<typename Iterator, typename UnaryFun>
auto maxElementBy(Iterator first, Iterator last, UnaryFun criterion)
    -> Iterator

Context

StackExchange Code Review Q#51552, answer score: 2

Revisions (0)

No revisions yet.