STL:写“哪里”向量的运算符
我需要根据几个布尔谓词找到向量中的索引。
例如:
vector<float> v;
vector<int> idx;
idx=where( bool_func1(v), bool_func2(v), ... );
如何声明 **where**
函数,以便在向量上使用多个用户定义的布尔函数?
谢谢 阿曼.
一周后编辑
我使用模板做了一些复杂的解决方案。但实际上,我们可以使用已经预定义的 valarray
来完成我的任务。这是代码片段,也许人们会发现它很有用:
double dr=Rc/(double)Nbins, r;
sigma.resize(Nbins);
rr=sigma;
valarray<double> vz(&data.vz[0], data.vz.size());
double mvel=vz.sum()/(double)vz.size();
for(size_t i=0l;i<Nbins;i++)
{
r=dr*i;
valarray<bool> ids = (dist < r+dr) && (dist > r);//The magic valarray<bool>
if(ids.max())
{
valarray<double> d=vz[ids];//we can use indirect operation.
d-=mvel;
d=pow(d,2.0);
sigma[i]= sqrt(d.sum()/(double)d.size());
rr[i]=r;
cout<<i<<") "<<r<<" "<<sigma[i]<<endl;
}
}
I need to find the indexes in the vector based on several boolean predicates.
ex:
vector<float> v;
vector<int> idx;
idx=where( bool_func1(v), bool_func2(v), ... );
What is the way to declare **where**
function, in order to use the several user defined boolean functions over the vector?
thanks
Arman.
Edit after one week
I did some complex solutions with templates. But in reality one can use already predefined valarray
for my tasks. Here is the code snippet maybe one can find it useful:
double dr=Rc/(double)Nbins, r;
sigma.resize(Nbins);
rr=sigma;
valarray<double> vz(&data.vz[0], data.vz.size());
double mvel=vz.sum()/(double)vz.size();
for(size_t i=0l;i<Nbins;i++)
{
r=dr*i;
valarray<bool> ids = (dist < r+dr) && (dist > r);//The magic valarray<bool>
if(ids.max())
{
valarray<double> d=vz[ids];//we can use indirect operation.
d-=mvel;
d=pow(d,2.0);
sigma[i]= sqrt(d.sum()/(double)d.size());
rr[i]=r;
cout<<i<<") "<<r<<" "<<sigma[i]<<endl;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
让你的 bool_xxx 函数实际上是特定类型的函子(标签调度就足够了)。然后覆盖 ||和&&对于他们来说,这些运算符返回 bool_and 或 bool_or。然后您可以像这样使用 bool_ 谓词:
如果您想编写一个“where”函数,那么您显然希望使用一组不同的 bool_xxx 函数多次执行此操作。即使你知道你现在想要某种类型的作品,你也可以让它尽可能通用。我就是这样做的。
编辑:
基于此评论:@Jerry:例如我需要知道: id=where(v < 10.0 && v>1.0);稍后我想知道: id=where(v < fun(v)); 你可能会更好地使用 boost::lambda:
或者,如果你讨厌 lambda 或不允许使用它...或者只是想要一个稍微好一点的语法(但无法直接使用函数),然后只需创建自己的占位符类型并覆盖它以在运算符 <、> 等上返回 bool_xxx 函子...
Edit2:这是一个未经测试,其中返回迭代器向量到所有匹配的对象:
它是递归的,并且在某些实现上可能很慢,但有一种方法可以做到这一点。
Make your bool_xxx functions actually functors of a specific kind of type (tag dispatching would be enough). Then override || and && for them such that these operators return a bool_and, or bool_or. Then you can use your bool_ predicates like so:
If you're tempted to write a "where" function then you apparently want to do this more than once with a different set of bool_xxx functions. Even if you know that you want a certain type of composition now, you may as well make it as universal as possible. This is how I'd do it.
Edit:
Based on this comment: @Jerry: For example I need to know: id=where(v < 10.0 && v>1.0); and somewhere later I would like to know: id=where(v < fun(v)); you may be better off with boost::lambda:
Or, if you hate lambda or aren't allowed to use it...or just want a very slightly nicer syntax (but inability to use functions directly) then just make your own placeholder type and override it to return bool_xxx functors on operators <, >, etc...
Edit2: Here's an untested where that returns a vector of iterators to all objects matching:
It's recursive and could be slow on some implementations but there's one way to do it.
您可以使用
transform
的谓词版本(如果有的话)。没有,但是很容易编写:然后您需要一种方法来组合多个谓词,以便您可以表达类似
find_if( begin, end, condition1 && condition2 )< /代码>。这同样很容易编写:
最后,您需要一个
transform_if
用来将对象引用转换为对象指针的小控件。惊喜,惊喜,容易写……让我们用一个具体的例子把这一切放在一起。下面的
Gizmo
是您拥有的集合的对象。我们有 2 个谓词find_letter
和find_value
,我们想要在主向量
中搜索匹配项。transform_if
是transform
的谓词版本,get_ptr
将对象引用转换为指针,binary_composite
将两种复合材料。编辑:
基于 sbi 的迭代方法,这里有一个
copy
的谓词版本,它更符合一般的 STL 范例,并且可以与back_insert_iterator
一起使用来完成本例中所需的功能。它会给你一个对象的向量
,而不是迭代器或索引,因此我上面发布的transform_if
仍然比copy_if
更适合这种用途。但这里是...You could use a predicated version of
transform
, if there were one. There's not one, but it is very easy to write:Then you would need a way to make a composite of multiple predicates, so that you could express something like
find_if( begin, end, condition1 && condition2 )
. This, again, is easy to write:Finally you need a gizmo that
transform_if
uses to convert an object reference to an object pointer. Surprise, surprise, easy to write...Let's put this all together with a concrete example.
Gizmo
below is the object that you have a collection of. We have 2 predicatesfind_letter
andfind_value
that we want to search for matches to in our mainvector
.transform_if
is the predicated version oftransform
,get_ptr
converts an object reference to a pointer, andbinary_composite
strings together the two composites.EDIT:
Based on sbi's iterative approach, here's a predicated version of
copy
, which is more in line with the general STL paradigm, and can be used withback_insert_iterator
to accomplish what's wanted in this case. It will give you avector
of object, not iterators or indexes, so thetransform_if
I posted above is still better for this use thancopy_if
. But here it is...这似乎是一个可以用 Prolog 这样的声明性语言更容易解决的问题。无论如何,我在 C++ 中尝试了一下:
This seems like a problem that could much easier be solved in an declarative language like Prolog. I gave it a try in C++ anyway:
我不确定你想要哪个索引。这是您想要实现的目标吗:
I am not sure which indexes you want. Is this what you are trying to acheive:
根据需要重载其他函数对象参数。使用:
诺亚·罗伯特的解决方案很好,但我不完全确定如何才能实现这一点。
Overload for additional function object arguments as you wish. Use:
Noah Robert's solution is nice, but I'm not wholly sure how I could make that work.