Using lower_bound() and upper_bound() to select records
I have a map of objects, keyed by a date (stored as a double). I want to filter/extract the objects based on date, so I wrote a function similar to the snippet below.
However, I found that if I provide a date that is either lower than the earliest date, or greater than the last date, the code fails. I have modified the code so that any input startdate that is lower than the first date is set to the first (i.e. lowest) date in the map, likewise, enddate > last date is set to the last (greatest) date in the map
void extractDataRecords(const DatedRecordset& recs, OutStruct& out, const double startdt, const double enddt)
{
double first = recs.begin()->first, last = recs.rbegin()->first;
const double sdate = (start < first) ? first : startdt;
开发者_开发知识库 const double edate = (enddt > last) ? last : enddt;
DatedRecordsetConstIter start_iter = recs.lower_bound(sdate), end_iter = recs.upper_bound(edate);
if ((start_iter != recs.end()) && (end_iter != recs.end()))
{
// do Something
}
}
Is this the correct way to achieve this behaviour?
std::lower_bound
returns: "the first position into which value
can be inserted without violating the ordering." std::upper_bound
returns: "the furthermost position into which value
can be inserted without violating the ordering." In other words, if you insert the new item at either position, you're guaranteed that the overall ordering of the collection remains intact.
If you're going to use both anyway, you should probably use std::equal_range
instead -- it returns an std::pair
of iterators, one that's the same as lower_bound
would have returned, and the other the same as upper_bound
would have returned. Although it has the same worst-case complexity as calling the two separately, it's usually faster than two separate calls.
It's worth noting, however that if what you have is really a map
(rather than a multimap
) there can only be one entry with a given key, so there's not much reason to deal with both lower_bound
and upper_bound
for any given key.
From GNU libstdc++
lower_bound: This function returns the first element of a subsequence of elements
that matches the given key. If unsuccessful it returns an iterator pointing to the first element that has a greater value than given key or end() if no such element exists
Your original approach on using lower_bound
sounds correct to me. However, I think you don't need to use upper_bound
, you can do a simple comparison with enddt
. I would try
for( DatadRecordsetConstIter cit = recs.lower_bound( startdt );
cit != rec.end(); ++cit ) {
if( *cit > enddt ) {
break;
}
// do stuff with *cit
}
精彩评论