views:

58

answers:

2

Hi all,

This is a pretty straightforward thing, but I've been bashing my head trying to understand. I'm trying to compare the elements of a vector<complex <double> > vec with a complex <double> num to check if num already exists on vec. If it does, it is not added. I tried to use the equal() and algorithm, with no success. Does anybody knows a fast way to do that?

Thank you

EDIT2 : I'm trying to do that for complex numbers as a simplification, as I also need to perform the same operation on a struct:

struct thing{
 int i;
 int j;
 complex <double> pos;
}typedef t_thing;

complex <double> new_num(2.0,2.0);
t_thing will_insert;
will_insert.i = 1;
will_insert.j = 1;
will_insert.pos = new_num;
vector<t_thing> vec_thing;
if(! (find(vec_thing.begin(),vec_thing.end(),will_insert) == vec_thing.end())){
  vec_thing.push_back(will_insert);
}else { 
 cout<<"element already on vec_thing"<<endl;
}

EDIT 3: I've overloaded the operator ==, but find cannot work with that:

: error: no matching function for call to ‘find(__gnu_cxx::__normal_iterator<thing*, std::vector<thing, std::allocator<thing> > >, __gnu_cxx::__normal_iterator<thing*, std::vector<thing, std::allocator<thing> > >, t_thing&)’
+3  A: 

The std::equal algorithm is used to compare 2 iterator ranges. So you would use it to compare, for example, 2 vectors to see if both vectors contain the same elements.

In your case, where you only need to check if a single element is inside the vector, you can just use std::find

if (std::find(vec.begin(), vec.end(), std::complex<double>(1,1)) == vec.end()) {
   /* did not find element */
}
else { /* found the element */ }

Note however that std::vector is not particularly well suited for lookup algorithms like this, since each lookup gives you O(N) complexity. You might want to think about using std::set, so you get logarithmic complexity for lookup, and automatic assurance that you don't have any duplicate elements.

Charles Salvia
+1 for using set if the OP is trying to enforce a uniqueness constraint.
Timo Geusch
Just realized that this contained my answer already :sigh:. Deleted my answer and +1.
Billy ONeal
Jim Brissom
Or, if insertions are relatively infrequent or the container is relatively small, a sorted `std::vector` may provide better performance (using `std::binary_search` and friends).
James McNellis
The g++ compiler keeps giving me errors about the compilation, saying that there is no matching function to call for complex <double>. It works for double. The floating point comparison problems can also appear.
Ivan
Also, it seems that using set, the order of the elements is changed, and I have to keep the insertion order.
Ivan
@Ivan, if you need to keep insertion order, then you'll have to settle for O(N) lookups, without having some kind of external index. Just use std::find with the vector.
Charles Salvia
@Charles, thank you. What kind of operator overload do I have to implement so find can work with the struct?
Ivan
@Ivan, you can overload the equality (`==`) operator for your `struct thing`, so that `std::find` knows how to compare two `struct things`
Charles Salvia
A: 

A contains helper function template makes this easy:

template <typename Iterator, typename T>
bool contains(Iterator first, Iterator last, const T& obj)
{
    return std::find(first, last, obj) != last;
}

template <typename Container, typename T>
bool contains(Container c, const T& obj)
{
    // in C++0x  you could use std::begin() and std::end() here:
    return contains(c.begin(), c.end(), obj);
}
James McNellis