This code will return false
if the long double rand
begins with any string in the vector prefix
.
bool prefix_vect(long double rand, std::vector<std::string> prefix) {
std::string str_rand = std::to_string(rand);
for(auto i : prefix) {
if(boost::starts_with(str_rand, i))
return false;
}
return true;
}
This code uses #include <boost/algorithm/string/predicate.hpp>
.
How can I improve this code? Is there a way to make it fit into one line, such that it could be used without a function at all, and instead in an if-statement?
I am not experienced with C++ lambda expressions, is this something that could use them?
As a note: I don't care if it returns true or false, the Boolean can be switched if it makes this easier to optimize.
Edit: This isn't my main account, just a throwaway (unable to merge accounts, sadly).
2 Answers 2
It's better to pass containers as references to avoid copying like this:
bool prefix_vect(long double rand, const std::vector<std::string>& prefix)
Also, when iterating on sequence, references also can improve performance:
for(const auto& i : prefix) {
As for one-liner I'd used something like this:
bool prefix_vect2(long double rand, const std::vector<std::string>& prefix) {
std::string str_rand = std::to_string(rand);
return std::none_of(prefix.begin(), prefix.end(),
[&str_rand](const std::string& s){ return boost::starts_with(str_rand, s); });
}
If speed (when comparing many numbers against a constant set of prefixes) is your concern:
Converting a number to a decimal string representation is quite expensive. For the example given, a comparison x>=0.1 && x<0.2
does the same thing as the "0.1" prefix and is MUCH faster. Of course you need to convert the prefix strings to the interval limits, but only once for all test numbers.
If clarity of code is your concern, rename the function to begins_with_prefix()
or similar, and otherwise leave it more or less the way it is. A call to a well-named function is always better understandable to a human reader than a line full of cryptic C++ constructs.
-
\$\begingroup\$ Your numeric approach won't work unless all numbers are of the same magnitude. Consider
10258
and the set of prefix strings{"103", "10"}
. \$\endgroup\$Edward– Edward2017年09月25日 12:48:09 +00:00Commented Sep 25, 2017 at 12:48 -
\$\begingroup\$ @Edward You're correct. But the examples given by OP imply that there might be a common magnitude or a given decimal point, so the approach might be useful to the OP. \$\endgroup\$Ralf Kleberhoff– Ralf Kleberhoff2017年09月25日 13:44:55 +00:00Commented Sep 25, 2017 at 13:44
Explore related questions
See similar questions with these tags.
--prefix 0.1 0.3
, and in the end it would print only the numbers beginning with 0.1 and 0.3 -- doing so by verifying it through this function. The numbers 0.1 and 0.3 are stored in a vector of strings, and the randomly generated numbers are long doubles, thus they need to be converted to a string to be compared easily. \$\endgroup\$