I have a graph made with the Boost's graph library. It is based on the adjaceny list structure. I have the following simple definition of a vertex.
struct Vertex
{
string unique_id_name;
};
I want to be able to test if a vertex with a given unique_id_name exists. How can you do this?
You can use std::find_if() - for example, suppose you are looking for vertex_im_looking_for.
If you are using C++11, you can plug in a lambda into std::find_if() - if not, you can plug in a standard functor (a predicate).
typename boost::graph_traits<Graph>::vertex_iterator vi, vi_end;
tie(vi, vi_end) = vertices(my_graph);
bool found = std::find_if(
vi, vi_end,
[&](const Vertex& vertex){
return vertex.unique_id_name==vertex_im_looking_for.unique_id_name;
}
)!=vi_end;
std::find_if() returns an iterator so you can compare with vi_end to see if you found what you are looking for. If it equals vi_end, your vertex was not found.
Related
I have a vector<triplet> where triplet is a custom datatype, which is defined as follows:-
struct triplet{
int in, g, o; //where in denotes index of a triplet element in the vector<triplet>
}
So I have a elements in my vector<triplet> as follows
vector<triplet> v= ({0,4,0},{1,2,0},{2,5,0},{3,4,0});
I have a few queries to do on this vector<triplet>
I want to use find_if algorithm to find out if a number x is already present in any of v[i].in present in the vector<triplet>, ie, I want to check if x matches to any of in of the triplet present in the vector<triplet> .
I found no examples to do this type of query on the internet. If there is some alternative to use instead of find_if please mention it.
Use a lambda function.
int value_to_find = ...;
find_if(v.begin(), v.end(), [=](const triplet& t){ return t.in == value_to_find; });
Any time you need a one-off function for some purpose a lambda function is the obvious choice.
Full disclosure, this may be a hammer and nail situation trying to use STL algorithms when none are needed. I have seen a reappearing pattern in some C++14 code I am working with. We have a container that we iterate through, and if the current element matches some condition, then we copy one of the elements fields to another container.
The pattern is something like:
for (auto it = std::begin(foo); it!=std::end(foo); ++it){
auto x = it->Some_member;
// Note, the check usually uses the field would add to the new container.
if(f(x) && g(x)){
bar.emplace_back(x);
}
}
The idea is almost an accumulate where the function being applied does not always return a value. I can only think of a solutions that either
Require a function for accessing the member your want to accumulate and another function for checking the condition. i.e How to combine std::copy_if and std::transform?
Are worse then the thing I want to replace.
Is this even a good idea?
A quite general solution to your issue would be the following (working example):
#include <iostream>
#include <vector>
using namespace std;
template<typename It, typename MemberType, typename Cond, typename Do>
void process_filtered(It begin, It end, MemberType iterator_traits<It>::value_type::*ptr, Cond condition, Do process)
{
for(It it = begin; it != end; ++it)
{
if(condition((*it).*ptr))
{
process((*it).*ptr);
}
}
}
struct Data
{
int x;
int y;
};
int main()
{
// thanks to iterator_traits, vector could also be an array;
// kudos to #Yakk-AdamNevraumont
vector<Data> lines{{1,2},{4,3},{5,6}};
// filter even numbers from Data::x and output them
process_filtered(std::begin(lines), std::end(lines), &Data::x, [](int n){return n % 2 == 0;}, [](int n){cout << n;});
// output is 4, the only x value that is even
return 0;
}
It does not use STL, that is right, but you merely pass an iterator pair, the member to lookup and two lambdas/functions to it that will first filter and second use the filtered output, respectively.
I like your general solutions but here you do not need to have a lambda that extracts the corresponding attribute.
Clearly, the code can be refined to work with const_iterator but for a general idea, I think, it should be helpful. You could also extend it to have a member function that returns a member attribute instead of a direct member attribute pointer, if you'd like to use this method for encapsulated classes.
Sure. There are a bunch of approaches.
Find a library with transform_if, like boost.
Find a library with transform_range, which takes a transformation and range or container and returns a range with the value transformed. Compose this with copy_if.
Find a library with filter_range like the above. Now, use std::transform with your filtered range.
Find one with both, and compose filtering and transforming in the appropriate order. Now your problem is just copying (std::copy or whatever).
Write your own back-inserter wrapper that transforms while inserting. Use that with std::copy_if.
Write your own range adapters, like 2 3 and/or 4.
Write transform_if.
I have a big container of boost::unordered_map like below:
typedef boost::unordered_map< vertex, entity > vertex_container;
The vertex class has a coordinate member variable representing its location.
I have several coordinate point_(s). I would like search if any vertex inside my container exist so that vertex.coordinate = point.
something like:
vertex_container::iterator it = std::find_if(v_container.begin(), v_container.end(), boost::bind(&Vertex::coordinate(), _1) == point);
but it fails.
I tried:
vertex_container::iterator it = std::find_if(v_container | boost::adaptors::map_keys(boost::bind(&vertex::coordinate(), _1)) == point);
error: cannot call member function ‘mesh::coordinate mesh::Vertex::coordinate() const’ without object.
I somehow try to combine boost unordered_map, bind, and std::find_if.
Please NOTE I am only able to use C++09 standard and boost 1.53.0 version.
what you need to do is to first bind the key out of the unordered_map and then bind again the member function.
vertex_container::iterator it = std::find_if( v_container.begin(), v_container.end(), (boost::bind(&vertex::coordinate, (boost::bind( &vertex_container::value_type::first, _1))) == point) );
and also you cannot use pipe within std::find_if.
In your code you have :
boost::bind(&Vertex::coordinate, _1) == point
this is a comparison between boost::bind(...) and point, and, since it is a comparison, it is a boolean value. Or more probably, your compiler doesn't know how to compare the two.
std::find_if takes a function returning boolean as argument.
This means, since you're on <c++11 you'll have to declare a function somewhere like:
bool isVertexEqualToPoint(Vertex*, point){
return vertex.coordinate==point;
}
and then you can boost::bind that function to compare against your point.
I do think however that is is more elegant here to make a compare object. Have a look at this question. It should be straightforward. Just replace the somehow_compare with your own condition.
I have a sequence of values that I'd like to pass to a function that takes a (iterator begin, iterator end) pair. However, I only want every second element in the original sequence to be processed.
Is there a nice way using Standard-Lib/Boost to create an iterator facade that will allow me to pass in the original sequence? I figured something simple like this would already be in the boost iterators or range libraries, but I didn't find anything.
Or am I missing another completely obvious way to do this? Of course, I know I always have the option of copying the values to another sequence, but that's not what I want to do.
Edit: I know about filter_iterator, but that filters on values - it doesn't change the way the iteration advances.
I think you want boost::adaptors::strided
struct TrueOnEven {
template< typename T >
bool operator()(const T&) { return mCount++ % 2 == 0; }
TrueOnEven() : mCount(0) {}
private:
int mCount;
};
int main() {
std::vector< int > tVec, tOtherVec;
...
typedef boost::filter_iterator< TrueOnEven, int > TakeEvenFilterType;
std::copy(
TakeEvenFilterType(tVec.begin(), tVec.end()),
TakeEvenFilterType(tVec.end(), tVec.end()),
std::back_inserter(tOtherVec));
}
To be honest, this is anything else than nice and intuitive. I wrote a simple "Enumerator" library including lazy integrated queries to avoid hotchpotch like the above. It allows you to write:
Query::From(tVec.begin(), tVec.end())
.Skip<2>()
.ToStlSequence(std::back_inserter(tOtherVec));
where Skip<2> basically instantiates a generalized "Filter" which skips every N-th (in this case every second) element.
Here's Boost's filter iterator. It is exactly what you want.
UPDATE: Sorry, read wrongly-ish. Here's a list of all iterator funkiness in Boost:
http://www.boost.org/doc/libs/1_46_1/libs/iterator/doc/#specialized-adaptors
I think a plain iterator_adaptor with an overloaded operator++ that increments the underlying iterator value twice is all you need.
I have a need to wrap a vector iterator, but don't like the idea to rewrite it from scratch. And I can't subclass it as far as vector iterator doesn't seem to be cross-platform. At least gnu and ibm ones look different.
What I want to do is the following:
class MyContainer {
vector<double> data;
vector<int> indices;
iterator
begin()
{ return my_iterator(data, indices.begin()); }
iterator
end()
{ return my_iterator(data, indices.end()); }
}
MyContainer cont;
Where indices vector contains integer positions within the data vector. Data is supposed to be much much bigger than the indices.
So I need an iterator that can go through the indices in any direction like a normal vector iterator does with the only exception: it must return a value of data vector when the value is going to be accessed. e.g.:
for(MyContainer::iterator it = cont.begin(); it != cont.end(); it++) {
cout << *it << endl; // values of data should appear here
}
Basically it should look like a normal collection for the std world. You can iterate it in whatever direction you want, you can sort it, run unique, find_if, etc...
any simple solution?
There's a great Boost library for defining custom iterators. You need to provide a class with a few methods:
i.dereference() Access the value referred to
i.equal(j) Compare for equality with j
i.increment() Advance by one position
i.decrement() Retreat by one position
i.advance(n) Advance by n positions
i.distance_to(j) Measure the distance to j
Then you get the rest from the iterator_facade.
Good luck!
This looks a lot like a permutation_iterator, one of the "built in" adapters from the Boost.Iterator Library
See this example (modified from the Boost docs) on codepad.
There's nothing in the standard C++ library, but you can probably get boost::iterator_adapter to do what you want. A preliminary examination suggests you'll need to override iterator_adapter::dereference and iterator_adapter::equal.
template <typename _Scalar=double,
typename _Idx=int,
typename _Seq=std::vector<_Scalar>,
typename _IdxVector=std::vector<_Idx> >
class SelIter
: public boost::iterator_adaptor< SelIter<_Scalar, _Idx>,
typename _IdxVector::iterator, _Scalar >
{
public:
typedef boost::iterator_adaptor< SelIter, typename _IdxVector::iterator, _Scalar > Base;
SelIter(_Seq& scalars, _IdxVector& idxs);
SelIter(_Seq& scalars, typename _IdxVector::iterator pi);
typename Base::reference dereference() const;
bool equal(const SelIter& x) const;
private:
// ...
}