Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ std::vector search for value

I am attempting to optimize a std::vector "search " - index based iterating through a vector and returning and element that matches a "search" criteria

struct myObj {
   int id;
   char* value;
};

std::vector<myObj> myObjList;

create a few thousand entries with unique id's and values and push them to the vector myObjList.

What is the most efficient way to retrieve myObj that matches the id. Currently I am index iterating like:

for(int i = 0; i < myObjList.size(); i++){
   if(myObjList.at(i).id == searchCriteria){
    return myObjList.at(i);
   }
}

Note: searchCriteria = int. All the elements have unique id's. The above does the job, but probably not the most efficient way.

like image 698
narkis Avatar asked Jan 02 '13 15:01

narkis


People also ask

How do I find a specific value in a vector C++?

You can use the find function, found in the std namespace, ie std::find . You pass the std::find function the begin and end iterator from the vector you want to search, along with the element you're looking for and compare the resulting iterator to the end of the vector to see if they match or not.

How do you check if a vector contains a value?

The simplest solution is to count the total number of elements in the vector having the specified value. If the count is nonzero, we have found our element. This can be easily done using the std::count function.

How do you find the element of a vector?

Use std::find_if() with std::distance() This is a recommended approach to finding an element in a vector if the search needs to satisfy a specific logic eg, finding an index of element in the vector that is a prime number using prime number logic.

How do you access a specific element in a vector?

Vector elements are accessed using indexing vectors, which can be numeric, character or logical vectors. You can access an individual element of a vector by its position (or "index"), indicated using square brackets. In R, the first element has an index of 1.


2 Answers

The C++ standard library has some abstract algorithms, which give C++ a kind of functional flavour, as I call it, which lets you concentrate more on the criteria of your search than on how you implement the search itself. This applies to a lot of other algorithms.

The algorithm you are looking for is std::find_if, a simple linear search through an iterator range.

In C++11, you can use a lambda to express your criteria:

std::find_if(myObjList.begin(), myObjList.end(), [&](const myObj & o) {
    return o.id == searchCriteria;
});

When not having C++11 available, you have to provide a predicate (function object (=functor) or function pointer) which returns true if the provided instance is the one you are looking for. Functors have the advantage that they can be parameterized, in your case you want to parameterize the functor with the ID you are looking for.

template<class TargetClass>
class HasId {
    int _id;
public:
    HasId(int id) : _id(id) {}
    bool operator()(const TargetClass & o) const {
        return o.id == _id;
    }
}

std::find_if(myObjList.begin(), myObjList.end(), HasId<myObj>(searchCriteria));

This method returns an iterator pointing to the first element found which matches your criteria. If there is no such element, the end iterator is returned (which points past the end of the vector, not to the last element). So your function could look like this:

vector<myObj>::iterator it = std::find_if(...);

if(it == myObjList.end())
    // handle error in any way
else
    return *it;
like image 161
leemes Avatar answered Oct 18 '22 21:10

leemes


Using std::find_if.

There's an example on the referenced page.

Here's a working example that more precisely fits your question:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct myObj
{
   int id;
   char* value;

   myObj(int id_) : id(id_), value(0) {}
};

struct obj_finder
{
    obj_finder(int key) : key_(key)
    {}

    bool operator()(const myObj& o) const
    {
        return key_ == o.id;
    }

    const int key_;
};

int main () {
  vector<myObj> myvector;
  vector<myObj>::iterator it;

  myvector.push_back(myObj(30));
  myvector.push_back(myObj(50));
  myvector.push_back(myObj(100));
  myvector.push_back(myObj(32));

  it = find_if (myvector.begin(), myvector.end(), obj_finder(100));
  cout << "I found " << it->id << endl;

  return 0;
}

And, if you have C++11 available, you can make this even more concise using a lambda:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct myObj
{
   int id;
   char* value;

   myObj(int id_) : id(id_), value(0) {}
};

int main ()
{
  vector<myObj> myvector;
  vector<myObj>::iterator it;

  myvector.push_back(myObj(30));
  myvector.push_back(myObj(50));
  myvector.push_back(myObj(100));
  myvector.push_back(myObj(32));

  int key = 100;

  it = find_if (myvector.begin(), myvector.end(), [key] (const myObj& o) -> bool {return o.id == key;});
  cout << "I found " << it->id << endl;

  return 0;
}
like image 11
Chad Avatar answered Oct 18 '22 19:10

Chad