Tutorial :Out of four std::vector objects select the one with the most elements



Question:

I have four std::vector containers that all might (or might not) contain elements. I want to determine which of them has the most elements and use it subsequently.

I tried to create a std::map with their respective sizes as keys and references to those containers as values. Then I applied std::max on the size() of each vector to figure out the maximum and accessed it through the std::map.

Obviously, this gets me into trouble once there is the same number of elements in at least two vectors.

Can anyone think of a elegant solution ?


Solution:1

You're severely overthinking this. You've only got four vectors. You can determine the largest vector using 3 comparisons. Just do that:

std::vector<blah>& max = vector1;  if (max.size() < vector2.size()) max = vector2;  if (max.size() < vector3.size()) max = vector3;  if (max.size() < vector4.size()) max = vector4;  

EDIT:

Now with pointers!

EDIT (280Z28):

Now with references! :)

EDIT:

The version with references won't work. Pavel Minaev explains it nicely in the comments:

That's correct, the code use references. The first line, which declares max, doesn't cause a copy. However, all following lines do cause a copy, because when you write max = vectorN, if max is a reference, it doesn't cause the reference to refer to a different vector (a reference cannot be changed to refer to a different object once initialized). Instead, it is the same as max.operator=(vectorN), which simply causes vector1 to be cleared and replaced by elements contained in vectorN, copying them.

The pointer version is likely your best bet: it's quick, low-cost, and simple.

std::vector<blah> * max = &vector1;  if (max->size() < vector2.size()) max = &vector2;  if (max->size() < vector3.size()) max = &vector3;  if (max->size() < vector4.size()) max = &vector4;  


Solution:2

Here's one solution (aside from Pesto's far-too-straightforward approach) - I've avoided bind and C++0x lambdas for explanatory purposes, but you could use them to remove the need for a separate function. I'm also assuming that with two vectors with an equal number of elements, which one is picked is irrelevant.

template <typename T> bool size_less (const T* lhs, const T* rhs) {      return lhs->size() < rhs ->size();  }    void foo () {      vector<T>* vecs[] = {&vec1, &vec2, &vec3, &vec4};      vector<T>& vec = std::min_element(vecs, vecs + 4, size_less<vector<T> >);  }  


Solution:3

Here is my very simple method. Only interest is that you just need basic c++ to understand it.

 vector<T>* v[] = {&v1, &v2, &v3, &v4}, *max=&v1;   for(int i=1; i < 4; ++i)       if (v[i]->size() > max->size()) max = v[i];  


Solution:4

This is a modified version of coppro's answer using a std::vector to reference any number of vectors for comparison.

template <typename T> bool size_less (const T* lhs, const T* rhs) {      return lhs->size() < rhs ->size();  }    void foo () {      // Define vector holding pointers to the original vectors      typedef vector< vector<T>* > VectorPointers;        // Fill the list      VectorPointers vecs;      vecs.push_back(&vec1);      vecs.push_back(&vec2);      vecs.push_back(&vec3);      vecs.push_back(&vec4);                vector<T>& vec = std::min_element(          vecs.begin(),           vecs.end(),           size_less<vector<T> >      );  }  


Solution:5

I'm all for over-thinking stuff :)
For the general problem of finding the highest/lowest element in a group, I would use a priority_queue with a comparator:
(copying shamelessly from coppro, and modifying...)

template <typename T> bool size_less (const T* lhs, const T* rhs)  {    return lhs->size() < rhs ->size();  }      vector* highest()  {    priority_queue<vector<T>, size_less<T> > myQueue;    ...    ...    return myQueue.top();  }    


Solution:6

You could use a std::multimap. That allows multiple entries with the same key.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »