简体   繁体   中英

Do boost accumulators support the calculation of minimum difference between adjacent values?

Assumption here is that I am receiving many values and I do not want to store them in the vector. So I would like to use something like boost accumulators. But in docs I can not find something like the logic I want.

Is there a way for me to have accumulator so that when called with

5, 10 , 12 , 15 , 27 it will output 2(minimal difference between two adjacent values, 10 and 12).

I know I can keep the last variable by myself and just use the acc(current-last) with tag::min, but I prefer to leave that to library if possible.

Not with the accumulators that are part of Boost, but you can write your own.

The accumulator itself will look something like this. Note that this version only handles an increasing sequence of values correctly, but does not required an initial sample. If you have different requirements you can tune this.

namespace boost {                           
namespace accumulators {                    
namespace impl {                            

template<typename Sample>
struct min_adjacent_difference_accumulator  
  : accumulator_base                        
{
    using result_type = Sample;
   
    template<typename Args>                 
    min_adjacent_difference_accumulator(Args const & args)
      : last_seen(args[sample | std::optional<Sample>{}])        
    {                                       
    }                                       
   
    template<typename Args>                 
    void operator ()(Args const & args)     
    {
        Sample new_value = args[sample];
        if (last_seen)
            min_diff = std::min(min_diff, new_value - *last_seen);
                                  
        last_seen = args[sample];
    }

    result_type result(dont_care) const     
    {                                       
        return min_diff;                   
    }
 private:
    std::optional<Sample> last_seen;
    Sample min_diff = std::numeric_limits<Sample>::max();
 };

 }}}

Putting it into the boost::accumulators::impl namespace is recommended in the documentation.

Next, we need a tag

namespace boost { namespace accumulators { namespace tag {

struct min_adjacent_difference                         
  : depends_on<>
{
    using impl = accumulators::impl::min_adjacent_difference_accumulator< mpl::_1 >;
};

}}}

and an extractor

namespace boost {
namespace accumulators {               
namespace extract {                    

inline extractor<tag::min_adjacent_difference> const min_adjacent_difference = {}; 
                                    
}
using extract::min_adjacent_difference;                    
                                    
}}

You can then use it like any of the accumulators provided by boost. You can check out an interactive version on compiler explorer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM