shashashamti2008
shashashamti2008

Reputation: 2337

Iterating through specific elements of a vector using another vector

Let's say I have a vector of strings as defined below.

std::vector<std::string> names;
names.push_back( "Zero"  );
names.push_back( "One"   );
names.push_back( "Two"   );
names.push_back( "Three" );
names.push_back( "Four"  );
names.push_back( "Five"  );
names.push_back( "Six"   );
names.push_back( "Seven" );
names.push_back( "Eight" );
names.push_back( "Nine"  );

Also, let's say I have a vector which defines which elements to loop through:

std::vector< int > indices;
indices.push_back( 0 );
indices.push_back( 5 );
indices.push_back( 6 );

How can I iterate on the vector names according to the elements of the vector indices to for example access names: "Zero", "Five", and "Six"? I know that:

for( vector<string>::iterator it=names.begin() ; it < names.end(); it++)

iterate over all elements or elements for which we can find a pattern, e.g., every other element, etc. But how about iterating over elements that have no pattern or difficult to find a pattern? How can a vector be used for iteration in another vector? Something like:

for( vector<int>::iterator it=indices.begin() ; it < indices.end(); it++ )
{
     names.at( indices.at( it ) )
     ...
}

Upvotes: 1

Views: 597

Answers (3)

Lukas
Lukas

Reputation: 1305

You can also use a std::for_each call with a lambda to access the indicies (version 1) Furthermore, you could use a range-based for loop with rvalues (version 2)

#include <vector>
#include <algorithm>  

int main()
{
  std::vector<std::string> names;
  names.push_back("Zero");
  names.push_back("One");
  names.push_back("Two");
  names.push_back("Three");
  names.push_back("Four");
  names.push_back("Five");
  names.push_back("Six");
  names.push_back("Seven");
  names.push_back("Eight");
  names.push_back("Nine");

  std::vector< int > indices;
  indices.push_back(0);
  indices.push_back(5);
  indices.push_back(6);

  // version 1
  std::for_each(std::cbegin(indices), std::cend(indices),
    [&](auto &idx) { std::cout << names.at(idx) << "\n";});

  // version 2
  for (auto &&idx : indices)
    std::cout << names.at(idx) << "\n";

  return 0;
}

Upvotes: 1

eerorika
eerorika

Reputation: 238461

Your suggestion is almost correct. Instead of insdices.at(it), you should dereference the iterator. But you can do it simply like this:

for(int index : indices) {
    names[index];
}

Or you can use vector::at if you cannot prove that names.size() > indices[i] for all i.

Upvotes: 3

Slava
Slava

Reputation: 44278

It is as simple as this:

for( vector<int>::iterator it=indices.begin() ; it != indices.end(); ++it )
{
     names.at( *it );
     names[*it]; // for faster but unvalidated access
     ...
}

Note: ++it could be faster (but cannot be slower) so it is usually used when you do not care if it is postfix or prefix form. it != container.end() also is usually used because it is more generic (less than works for random access iterator, but would not for forward iterator for example).

Upvotes: 2

Related Questions