std :: find / find_if与for循环 [英] std::find / find_if versus for loop

查看:211
本文介绍了std :: find / find_if与for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



尝试使用函数对象更加适应。作为我测试的一部分,请考虑:


#include< vector>

#include< iostream>

#include< algorithm>

#include< stdexcept>

#include< bitset>


使用std :: vector;

使用std :: cout;

使用std :: endl;

使用std :: ostream;


使用std :: bitset;


class bar {

int iden;

public:

bar(int id):iden(id){}

int get_id()const {return iden; }

};

class my_foo {

typedef std :: vector< bar> BAR_VEC;

BAR_VEC bv;


public:

my_foo()

{

bv.push_back(bar(0));

bv.push_back(bar(1));

bv.push_back(bar(3)) ;

}

void find(int id_to_find)

{

BAR_VEC :: const_iterator end = bv.end ();

for(BAR_VEC :: iterator it = bv.begin(); it!= end; ++ it)

{

if(id_to_find == it-> get_id())

{

std :: cout<< "找到了 << id_to_find<< std :: endl;

}

}

// BAR_VEC seg_iter = std :: find(

/ / bv.begin(),bv.end(),

// XXX); // XXX现在是花哨的仿函数或谓词业务 - 我想b $ b假设


}

};

int main()

{

my_foo m;

m.find(0);

m .find(1);

m.find(9);

}


现在在find函数中。我想使用std :: find或

std :: find_if来获得与for循环相同的结果,但我是

缠绕在试图将'参数/仿函数''插入'找到的第三个参数


再次这是纯粹的实验。在这里阅读一篇文章,我只是在尝试创建示例时尝试创建示例,以试图接受

迭代容器的不同视图/(必要时) )调用

成员函数等超出常规for循环。

解决方案

有不同的方法可以顺其自然,但我会选择

之类的:


struct IsId:public std :: binary_function< int,bar,bool> {

bool operator()(int anId,const bar& aBar)const {

返回anId == aBar.get_id();

}

};


BAR_VEC :: const_iterator seg_iter = std :: find_if(bv.begin(),bv.end(),

std :: bind1st(IsId(),id_to_find));

if(seg_iter!= bv.end()){

std :: cout< ;< "找到了 << id_to_find<< std :: endl;

}


恕我直言如果你使用std :: for_each它更漂亮,但这种方法有

更有效的快速失败。


--Chris


BAR_VEC :: const_iterator seg_iter = std :: find_if(bv.begin(),bv.end(),
std :: bind1st(IsId(),id_to_find));
if(seg_iter!= bv .end()){
std :: cout<< "找到了 << id_to_find<< std :: endl;
}

如果你使用std :: for_each,它会更漂亮,但是这种方法可以更有效地快速失败。




我正在阅读带有状态的功能对象(无论这意味着什么 -

还没有想到''状态'')导致

传递给for_each时的结果不可预测。


我还没弄明白如何检查bv.end但是接下来是什么

到目前为止:


std :: for_each(bv.begin(),bv.end(),std :: bind1st(IsId(),id_to_find );


在文章< 11 ********************** @ g14g2000cwa.googlegroups .com>,

" ma740988" <毫安****** @ gmail.com>写道:

尝试使用函数对象更加适应。作为我考试的一部分,请考虑:

#include< vector>
#include< iostream>
#include< algorithm>
#include< stdexcept>
#include< bitset>

使用std :: vector;
使用std :: cout;
使用std :: endl;
使用std :: ostream;

使用std :: bitset;

类吧{
int iden;
public:
bar(int id):iden(id){}
int get_id()const {return iden; }
};
类my_foo {
typedef std :: vector< bar> BAR_VEC;
BAR_VEC bv;

公开:
my_foo()
{
bv.push_back(bar(0));
bv .push_back(bar(1));
bv.push_back(bar(3));
}
void find(int id_to_find)
{
BAR_VEC :: const_iterator end = bv.end();
for(BAR_VEC :: iterator it = bv.begin(); it!= end; ++ it)
{
if(id_to_find == it-> get_id())
{
std :: cout<< "找到了 << id_to_find<< std :: endl;
}
// BAR_VEC seg_iter = std :: find(
// bv.begin(),bv.end(), // XXX); // XXX现在是花哨的仿函数或谓词业务 - 我想

}
};

int main()
{
my_foo m;
m.find(0);
m.find(1);
m.find(9);
}
std :: find_if来获得与for循环相同的结果,但是我要绕着轴试图堵塞参数/仿函数
进入查找的第三个参数。
这也是纯粹的实验。在这里阅读文本,我只是在尝试创建示例时,试图拥抱不同的迭代跨容器的视图/(必要时)调用
成员函数除了传统的for循环之外。




首先我会给出答案,然后我会解释我是如何到达那里的。


答案是:


void my_foo :: find(int id_to_find){

if(find_if(bv.begin(), bv.end(),compose1(bind2nd(equal_to< int>(),

id_to_find),mem_fun_ref(& bar :: get_id)))!= bv.end())

cout<< 找到 << id_to_find<< " \ n";

}


现在我是如何得出答案的?


首先将整个内容提取到一个结构中:


struct foo:public unary_function< bar,bool> {

int id_to_find;

foo(int i):id_to_find(i){}

bool operator()(const bar& bar_) const {

return bar_.get_id()== id_to_find;

}

};


void my_foo :: find(int id_to_find)

{

if(find_if(bv.begin(),bv.end(),foo(id_to_find))!= bv.end())

cout<< 找到 << id_to_find<< " \ n";

}


(注意:在我拿出一个
$之前我真的必须这样做b $ b回答,其余的我通常可以得到,而不必每一步实际编译

。换句话说,通过练习,你应该可以直接从
开始以上是正确的答案。)


现在我们将一些内容梳理成标准的仿函数。我们这里的目标

最终会得到一个接受条形对象的仿函数,因为它是容器中的元素。


''foo''struct'的op()中发生的最后一件事是

比较,所以:


struct foo:public unary_function< bar,bool> {

int id_to_find;

foo(int i):id_to_find(i){}

bool operator()(const bar& bar_) const {

equal_to< int> a = equal_to< int>();

返回a(bar_.get_id(),id_to_find);

}

};


现在我们有一个接受两个整数的仿函数'''',其中一个来自

我们的bar对象。让我们通过绑定来删除第二个int

second arg:


struct foo:public unary_function< bar,bool> {

int id_to_find;

foo(int i):id_to_find(i){}

bool operator()(const bar& bar_) const {

binder2nd< equal_to< int> > b =

bind2nd(equal_to< int>(),id_to_find);

返回b(bar_.get_id());

}

};


现在我们有一个仿函数''''接受bar :: get_id的结果。让's $

将它绑定到一个仿函数中:


struct foo:public unary_function< bar,bool> {

int id_to_find;

foo(int i):id_to_find(i){}

bool operator()(const bar& bar_) const {

binder2nd< equal_to< int> > b =

bind2nd(equal_to< int>(),id_to_find);

const_mem_fun_ref_t< int,bar> c =

mem_fun_ref(& bar :: get_id);

返回b(c(bar_));

}

};


现在我们的functor''''接受一个bar对象,但它需要

将结果传递给另一个仿函数,std

命名空间中没有任何东西可以帮助我们。幸运的是,有一个STL仿函数

可以完成这项工作。 < http://www.sgi.com/tech/stl/unary_compose.html>


struct foo:public unary_function< bar,bool> {

int id_to_find;

foo(int i):id_to_find(i){}

bool operator()(const bar& bar_) const {

stl :: unary_compose< binder2nd< equal_to< int> >,

const_mem_fun_ref_t< int,bar> > d =

compose1(bind2nd(equal_to< int>(),id_to_find),

mem_fun_ref(& bar :: get_id));

返回d(bar_);

}

};


我们走了。仿函数''''接受一个条形对象并返回我们想要的

结果。只需将''my_foo :: find''

函数中的''foo''仿函数替换为上面''d =''左边的所有内容。


这是''unary_compose''和''compose1''仿函数和函数......


模板< typename Op1,typename Op2>

class unary_compose:

public std :: unary_function< typename Op2 :: argument_type,

typename Op1 :: result_type>

{

Op1 fn1;

Op2 fn2;

public:

unary_compose(const Op1& x,const Op2& y):fn1(x),fn2(y){}

typename Op1 :: result_type operator()(const typename

Op2 :: argument_type& x)const {

返回fn1(fn2(x));

}

};


模板< ; typename Op1,typename Op2>

inline unary_compose< Op1,Op2> compose1(const Op1& fn1,const Op2& fn2){

返回unary_compose< Op1,Op2>(fn1,fn2);

}



Trying to get more acclimated with the use of function objects. As
part of my test, consider:

# include <vector>
# include <iostream>
# include <algorithm>
#include <stdexcept>
#include <bitset>

using std::vector;
using std::cout;
using std::endl;
using std::ostream;

using std::bitset;

class bar {
int iden;
public:
bar(int id) : iden(id) {}
int get_id() const { return iden; }
};
class my_foo {
typedef std::vector <bar> BAR_VEC;
BAR_VEC bv;

public:
my_foo()
{
bv.push_back(bar(0));
bv.push_back(bar(1));
bv.push_back(bar(3));
}
void find ( int id_to_find )
{
BAR_VEC::const_iterator end = bv.end();
for ( BAR_VEC::iterator it = bv.begin(); it != end; ++it )
{
if ( id_to_find == it->get_id() )
{
std::cout << " found " << id_to_find << std::endl;
}
}
// BAR_VEC seg_iter = std::find(
// bv.begin(), bv.end(),
// XXX ); // XXX now the fancy functor or predicate business - i
suppose

}
};
int main()
{
my_foo m;
m.find( 0 ) ;
m.find( 1 ) ;
m.find( 9 ) ;
}

Now within the find function. I''d like to use std::find or
std::find_if to achieve the same result as the for loop but I''m
getting wrapped around the axle trying to ''plug'' a parameter/functor
into the third argument of find.
Again this is pure experiment. Perusing a text here and I''m just
trying to create examples as I go along, in an attempt to embrace
different views of iterating across containers/ (where necessary ) call
member functions etc. beyond the convential for loop.

解决方案

There are different ways to go with this, but I''d go with something
like:

struct IsId : public std::binary_function<int, bar, bool> {
bool operator()(int anId, const bar& aBar) const {
return anId == aBar.get_id();
}
};

BAR_VEC::const_iterator seg_iter = std::find_if(bv.begin(), bv.end(),
std::bind1st(IsId(), id_to_find));
if (seg_iter != bv.end()) {
std::cout << " found " << id_to_find << std::endl;
}

IMHO it''s prettier if you use std::for_each, but this approach has the
more efficient fast failure.

--Chris


BAR_VEC::const_iterator seg_iter = std::find_if(bv.begin(), bv.end(),
std::bind1st(IsId(), id_to_find));
if (seg_iter != bv.end()) {
std::cout << " found " << id_to_find << std::endl;
}

IMHO it''s prettier if you use std::for_each, but this approach has the
more efficient fast failure.



I''m reading that function objects with state( whatever that means-
haven''t figured out ''state'' yet ) leads to unpredictable results when
passed to for_each.

I haven''t figured out how to check against bv.end yet but heres what
I''ve got thus far:

std::for_each(bv.begin(), bv.end(), std::bind1st(IsId(), id_to_find));


In article <11**********************@g14g2000cwa.googlegroups .com>,
"ma740988" <ma******@gmail.com> wrote:

Trying to get more acclimated with the use of function objects. As
part of my test, consider:

# include <vector>
# include <iostream>
# include <algorithm>
#include <stdexcept>
#include <bitset>

using std::vector;
using std::cout;
using std::endl;
using std::ostream;

using std::bitset;

class bar {
int iden;
public:
bar(int id) : iden(id) {}
int get_id() const { return iden; }
};
class my_foo {
typedef std::vector <bar> BAR_VEC;
BAR_VEC bv;

public:
my_foo()
{
bv.push_back(bar(0));
bv.push_back(bar(1));
bv.push_back(bar(3));
}
void find ( int id_to_find )
{
BAR_VEC::const_iterator end = bv.end();
for ( BAR_VEC::iterator it = bv.begin(); it != end; ++it )
{
if ( id_to_find == it->get_id() )
{
std::cout << " found " << id_to_find << std::endl;
}
}
// BAR_VEC seg_iter = std::find(
// bv.begin(), bv.end(),
// XXX ); // XXX now the fancy functor or predicate business - i
suppose

}
};
int main()
{
my_foo m;
m.find( 0 ) ;
m.find( 1 ) ;
m.find( 9 ) ;
}

Now within the find function. I''d like to use std::find or
std::find_if to achieve the same result as the for loop but I''m
getting wrapped around the axle trying to ''plug'' a parameter/functor
into the third argument of find.
Again this is pure experiment. Perusing a text here and I''m just
trying to create examples as I go along, in an attempt to embrace
different views of iterating across containers/ (where necessary ) call
member functions etc. beyond the convential for loop.



First I''ll give the answer, then I''ll explain how I got there.

The answer is:

void my_foo::find(int id_to_find) {
if (find_if(bv.begin(), bv.end(), compose1(bind2nd(equal_to<int>(),
id_to_find ), mem_fun_ref( &bar::get_id ) ) ) != bv.end() )
cout << "found " << id_to_find << "\n";
}

Now how did I come up with that answer?

First just extract the entire guts into a struct:

struct foo : public unary_function<bar, bool> {
int id_to_find;
foo(int i): id_to_find(i) { }
bool operator()(const bar& bar_) const {
return bar_.get_id() == id_to_find;
}
};

void my_foo::find(int id_to_find)
{
if (find_if(bv.begin(), bv.end(), foo(id_to_find)) != bv.end())
cout << "found " << id_to_find << "\n";
}

(Note: I really have to do the above before I can come up with an
answer, the rest I can usually get without having to actually compile
each step. In other words, with practice, you should be able to go
straight from the above to the correct answer.)

Now we tease out some of the guts into standard functors. Our goal here
is to end up with a functor that accepts a ''bar'' object because that is
what is in the container.

The last thing that happens in the ''foo'' struct''s op() is the
comparison, so:

struct foo : public unary_function<bar, bool> {
int id_to_find;
foo(int i): id_to_find(i) { }
bool operator()(const bar& bar_) const {
equal_to<int> a = equal_to<int>();
return a(bar_.get_id(), id_to_find);
}
};

Now we have a functor ''a'' that accepts two ints, one of which comes from
our bar object. Let''s remove the second int from it by binding that
second arg:

struct foo : public unary_function<bar, bool> {
int id_to_find;
foo(int i): id_to_find(i) { }
bool operator()(const bar& bar_) const {
binder2nd<equal_to<int> > b =
bind2nd(equal_to<int>(), id_to_find);
return b(bar_.get_id());
}
};

Now we have a functor ''b'' that accepts the results of bar::get_id. Let''s
bind that up into a functor as well:

struct foo : public unary_function<bar, bool> {
int id_to_find;
foo(int i): id_to_find(i) { }
bool operator()(const bar& bar_) const {
binder2nd<equal_to<int> > b =
bind2nd(equal_to<int>(), id_to_find);
const_mem_fun_ref_t<int, bar> c =
mem_fun_ref(&bar::get_id);
return b(c(bar_));
}
};

Now we have our functor ''c'' that accepts a bar object, but it needs to
pass its results to another functor, and there is nothing in the std
namespace that can help us. Fortunately, there is an STL functor that
can do the job. <http://www.sgi.com/tech/stl/unary_compose.html>

struct foo : public unary_function<bar, bool> {
int id_to_find;
foo(int i): id_to_find(i) { }
bool operator()(const bar& bar_) const {
stl::unary_compose<binder2nd<equal_to<int> >,
const_mem_fun_ref_t<int, bar> > d =
compose1(bind2nd(equal_to<int>(), id_to_find),
mem_fun_ref(&bar::get_id));
return d(bar_);
}
};

There we go. The functor ''d'' accepts a bar object and returns the
results we wanted. Just replace the ''foo'' functor in the ''my_foo::find''
function with everything to the left of the ''d ='' above.

Here is that ''unary_compose'' and ''compose1'' functor and function...

template <typename Op1, typename Op2>
class unary_compose:
public std::unary_function<typename Op2::argument_type,
typename Op1::result_type>
{
Op1 fn1;
Op2 fn2;
public:
unary_compose(const Op1& x, const Op2& y): fn1(x), fn2(y) {}
typename Op1::result_type operator()(const typename
Op2::argument_type& x) const {
return fn1(fn2(x));
}
};

template <typename Op1, typename Op2>
inline unary_compose<Op1, Op2> compose1(const Op1& fn1, const Op2& fn2) {
return unary_compose<Op1, Op2>(fn1, fn2);
}


这篇关于std :: find / find_if与for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆