开发者

Idiomatic C++ for finding a range of equal length strings, given a vector of strings (ordered by length)

given a std::vector< std::string >, the vector is ordered by string length, how can I find a range of equal length strength?

I am looking forward an idiomatic solution in C++.

I have found this solution:

// any idea for a better name? (English is not my mother tongue)
bool less_length( const std::string& lhs, const std::string& rhs )
{
    return lhs.length() < rhs.length();
}

std::vector< std::string > words;
words.push_back("ape");
words.push_back("cat");
words.push_back("dog");
words.push_back("camel");
size_t length = 3;
// this will give a range from "ape" to "dog" (included):
std::equal_range( words开发者_StackOverflow社区.begin(), words.end(), std::string( length, 'a' ), less_length );

Is there a standard way of doing this (beautifully)?


I expect that you could write a comparator as follows:

struct LengthComparator {
    bool operator()(const std::string &lhs, std::string::size_type rhs) {
        return lhs.size() < rhs;
    }
    bool operator()(std::string::size_type lhs, const std::string &rhs) {
        return lhs < rhs.size();
    }
    bool operator()(const std::string &lhs, const std::string &rhs) {
        return lhs.size() < rhs.size();
    }
};

Then use it:

std::equal_range(words.begin(), words.end(), length, LengthComparator());

I expect the third overload of operator() is never used, because the information it provides is redundant. The range has to be pre-sorted, so there's no point the algorithm comparing two items from the range, it should be comparing items from the range against the target you supply. But the standard doesn't guarantee that. [Edit: and defining all three means you can use the same comparator class to put the vector in order in the first place, which might be convenient].

This works for me (gcc 4.3.4), and while I think this will work on your implementation too, I'm less sure that it is actually valid. It implements the comparisons that the description of equal_range says will be true of the result, and 25.3.3/1 doesn't require that the template parameter T must be exactly the type of the objects referred to by the iterators. But there might be some text I've missed which adds more restrictions, so I'd do more standards-trawling before using it in anything important.


Your way is definitely not unidiomatic, but having to construct a dummy string with the target length does not look very elegant and it isn't very readable either.

I'd perhaps write my own helper function (i.e. string_length_range), encapsulating a plain, simple loop through the string list. There is no need to use std:: tools for everything.


std::equal_range does a binary search. Which means the words vector must be sorted, which in this case means that it must be non-decreasing in length.

I think your solution is a good one, definitely better than writing your own implementation of binary search which is notoriously error prone and hard to prove correct.

If doing a binary search was not your intent, then I agree with Alexander. Just a simple for loop through the words is the cleanest.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜