[英]string validation in std::vector
I am working on a code where I need to validate a std::vector
filled with multiple std::string
objects. 我正在编写需要验证由多个
std::string
对象填充的std::vector
的代码。 The logic is that I need to check if all of the objects are valid or not. 逻辑是我需要检查所有对象是否有效。 If yes then display a message saying that input vector is valid, error otherwise.
如果是,则显示一条消息,指出输入向量有效,否则错误。 Here is what I have so far.
这是我到目前为止所拥有的。
#include<iostream>
#include<vector>
#include<numeric>
#include<boost/foreach.hpp>
short multiply(short s1,short s2)
{
return s1*s2;
}
bool validate(const std::vector<std::string> &in)
{
std::vector<short>check(in.size(),0);
auto checkitr = check.begin();
BOOST_FOREACH(std::string str,in)
{
for(auto itr = str.begin(); itr != str.end(); ++itr)
{
if(*itr == 'c')
{
*checkitr = 1;
break;
}
}
++checkitr;
}
short product = std::accumulate(check.begin(),check.end(),1,multiply);
return ( (product) ? true : false );
}
int main()
{
std::string s1("abcd");
std::string s2("lncd");
std::vector<std::string>iVec;
iVec.push_back(s1);
iVec.push_back(s2);
bool isValid = validate(iVec);
if(isValid){
std::cout<<"This Vector is valid "<<std::endl;
}
else
{
std::cout<<"This is an invalid vector "<<std::endl;
}
iVec.push_back(std::string("ghkd"));
isValid = validate(iVec);
if(isValid){
std::cout<<"This Vector is valid "<<std::endl;
}
else
{
std::cout<<"This is an invalid vector "<<std::endl;
}
return 0;
}
This runs fine and gives me the result that I need.My question is, Is there any other better/performance efficient approach in standard algorithm or boost library that I can use instead of my current approach? 这样可以很好地运行,并为我提供所需的结果。我的问题是,在标准算法或Boost库中是否还有其他方法可以代替当前方法使用,从而提高性能?
It would have been nice to include a description of what the validation algorithm should validate, but I suppose the source is self-documenting. 包括对验证算法应验证哪些内容的描述将是不错的选择,但我想消息来源是自我记录。 To find out whether a vector of strings contains only strings that contain a
c
, I'd use 为了找出字符串向量是否仅包含包含
c
字符串,我将使用
#include <algorithm> // for std::none_of
#include <iterator> // for std::begin, std::end
bool validate(const std::vector<std::string> &in)
{
return std::none_of(std::begin(in),
std::end (in),
[](std::string const &s) {
return s.find('c') == std::string::npos;
});
}
std::none_of
checks if no element in a range satisfies a condition, and the [](std::string const &s) { ... }
is a lambda expression that describes the condition std::none_of
is supposed to use. std::none_of
检查范围内是否没有元素满足条件,并且[](std::string const &s) { ... }
是一个lambda表达式,用于描述应使用的条件std::none_of
。 Put together, this checks whether there is a string that doesn't contain a c
in the vector, returns true
if there wasn't and false
if there was. 放在一起,这将检查向量中是否存在不包含
c
的字符串,如果不存在则返回true
如果存在则返回false
。
The main runtime advantage over your code of this is that it stops checking as soon as it finds a string that doesn't contain a c
; 相对于此代码,运行时的主要优点是,一旦找到不包含
c
的字符串,它将立即停止检查; other than that, it is mostly shorter (unless the implementation of std::string::find
contains clever optimizations, which is not impossible). 除此之外,它通常更短(除非
std::string::find
包含巧妙的优化,这并非不可能)。
Side note: It would be possible to leave out many of the std::
in that code because of argument-dependent name lookup . 旁注:由于依赖于参数的名称查找,可能会在该代码中遗漏许多
std::
。 I left some out in the original code but put them back in after @BoBTFish commented on it to avoid confusion; 我在原始代码中省略了一些内容,但在@BoBTFish对它进行注释后再放回去,以避免造成混淆; I tend to leave them out for
begin
and end
because I'm used to doing it. 我倾向于将它们留给
begin
和end
因为我已经习惯了。 This is because of a (somewhat) useful trick in the context of templates that has no real bearing on the above function, but here it is (if you're interested): 这是因为在模板的上下文中有一个(某种)有用的技巧,与上面的功能没有实际的联系,但是这里是(如果您有兴趣的话):
If you want this validation routine to work for more than vectors, you could write 如果您希望此验证例程可用于多个向量,则可以编写
template<typename Container>
bool validate(Container &&in)
{
using std::begin;
using std::end;
return std::none_of(begin(std::forward<Container>(in)),
end (std::forward<Container>(in)),
[](std::string const &s) {
return s.find('c') == std::string::npos;
});
}
This is adapted from a similar technique for std::swap
described in Effective C++ by Scott Meyers; 这是由Scott Meyers在Effective C ++中描述的
std::swap
的类似技术改编而成; the useful thing about it is that if there are fitting implementations of begin(...)
and end(...)
in the namespace where the type to which Container
refers is defined, they are preferred over std::begin
and std::end
-- which is good because if they exist, it is sane to assume that they provide a better fit. 有用的是,如果在定义
Container
引用的类型的名称空间中有begin(...)
和end(...)
合适实现,则它们比std::begin
和std::end
更可取std::end
很好,因为如果它们存在,则假定它们提供更好的匹配度是理智的。
(Granted that std::begin
and std::end
's default behavior of using the .begin()
and .end()
member functions makes such implementations of begin
and end
mostly unnecessary, but I have seen stranger things in real-life code.) (授予
std::begin
和std::end
使用.begin()
和.end()
成员函数的默认行为,使得这些begin
和end
大都是不必要的,但是我在现实生活中已经看到了一些奇怪的事情码。)
EDIT: I didn't think of std::none_of
right away; 编辑:我没想到
std::none_of
马上; the original solution used std::find_if
. 原始解决方案使用
std::find_if
。 std::find_if
also works, of course, but std::none_of
is rather obviously a better fit. std::find_if
当然也可以,但是std::none_of
显然更合适。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.