开发者

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
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜