CodersSC
CodersSC

Reputation: 710

Copying C++ Map into key and value vectors

I have a map and I want the first column i.e (*it).first to be pushed back into a vector then (*it)->second to be pushed back into another vector

Is this the best way to do it?

std::vector<std::string>test;
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
    test.push_back((*it).first);
}

My other question is if i have a loop i.e how would I insert all the integers i into (*it).first?

for(int i = 0; i < 10; i++)
{
    // 1 - 10 will go in (*it).first
}

I want to have some integers in (*it).first and have associated values in (*it).second;

Upvotes: 5

Views: 18731

Answers (8)

Robᵩ
Robᵩ

Reputation: 168616

Your first question, "how can I push the first column of my map into one vector and the 2nd column into another" is solved thus:

std::map<std::string, std::string> mymap;
std::vector<std::string> keys;
std::vector<std::string> values;
for ( std::map<std::string,std::string>::iterator it=mymap.begin() ; it != mymap.end(); ++it )
{
  keys.push_back(it->first);
  values.push_back(it->second);
}

Your second question, "how would insert all the integers i into (*it).first ?" is solved thus:

std::map<int, int> mymap2;
for(int i = 0; i < 10; i++)
{
  // Insert default value into map
  // This sets '(*it).first' to 'i' and
  // '(*it).second' to a default value (in
  // this case, 0).
  mymap2[i];
}

or

std::map<int, int> mymap3;
for(int i = 0; i < 10; i++)
{
  // Insert specified value into map
  // this sets '(*it).first' to 'i', and
  // '(*it).second' to the value returned from the function.
  maymap3[i] = ChooseSpecificValue(i);
}

Upvotes: 2

Open AI - Opting Out
Open AI - Opting Out

Reputation: 24133

Use std::transform.

First define two functions key and value which take the pair of strings and return the first or second value, respectively.

#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

const std::string& key(const std::pair<std::string, std::string>& keyValue)
{
    return keyValue.first;
}

const std::string& value(const std::pair<std::string, std::string>& keyValue)
{
    return keyValue.second;
}

Then use std::transform from <algorithm> with the functions to transform the map into either a vector of keys or a vector of values.

int main()
{
    using namespace std; // be explicit normally, trying to be brief here

    map<string, string> contacts;

    contacts["alice"] = "555-2701";
    contacts["bob"] = "555-2702";

    vector<string> keys(contacts.size());
    vector<string> values(contacts.size());

    transform(contacts.begin(), contacts.end(), keys.begin(), key);
    transform(contacts.begin(), contacts.end(), values.begin(), value);

    cout << "Keys:\n";
    copy(keys.begin(), keys.end(), ostream_iterator<string>(cout, "\n"));

    cout << "\n";

    cout << "Values:\n";
    copy(values.begin(), values.end(), ostream_iterator<string>(cout, "\n"));

    return 0;
}

Output:

Keys:
alice
bob

Values:
555-2701
555-2702

Upvotes: 5

Matthieu M.
Matthieu M.

Reputation: 299740

Well, it can be done with a simple loop:

for (auto const& p: mymap) {
  vec1.push_back(p.first);
  vec2.push_back(p.second);
}

Or using the std::transform algorithm, though it's quite verbose here:

std::transform(mymap.begin(), mymap.end(), std::back_inserter(vec1),
               [](MyMap::const_reference p) { return p.first; });

Upvotes: 2

Dave
Dave

Reputation: 266

Just in case you want to deal with different data types in your map I would template a generic copy function:

template <class A, class B>
void mycopy(std::map<A, B>&m, std::list<A>& keys, std::list<B>& values) {
    typename std::map<A, B>::iterator it;
    for (it = m.begin(); it != m.end(); ++it) {
        keys.push_back( (*it).first );
        values.push_back( (*it).second );   
    }

}

Mixing it up:

std::map<int, std::string> mymap;
std::list<int> keys;
std::list<std::string> values;

mymap[1] = "string1";
mymap[2] = "string2";

mycopy(mymap, keys, values);


std::map<std::string, int> mymap1;
std::list<std::string> keys1;
std::list<int> values1;

mymap1["string1"] = 1;
mymap1["string2"] = 2;

mycopy(mymap1, keys1, values1);

Edit: yes __copy isnt the best definition. Thanks

Upvotes: 0

ManiP
ManiP

Reputation: 733

Assuming you've declared your map as string key and value (ie map<string, string> mymap; then it would be like below, also assuming you've declare 'it' variable as map<string, string>::iterator it, etc:

std::vector<std::string> test;
std::vector<std::string> second;
std::map<string, string>::iterator it;

for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
    test.push_back((*it).first);
    second.push_back((*it).second);
}

Not sure about your next question.

Upvotes: 1

Invictus
Invictus

Reputation: 4328

it here will be an iterator which will point to one of the position in map and at max have one first and second value for one iterator . At max you can have multiple key or same key holding same/different values depending on key/value combination.

As far as pushing the value in the vector for a key in map is concern you can do it in the same way you are pushing the key

     std::vector<std::string>test;

      std::vector<std::string>test2; 

      for ( it=mymap.begin() ; it != mymap.end(); it++ )


     {

       test.push_back((*it).first); 

      test2.push_back((*it).second);


     }

Neways yours question is very unclear .

Upvotes: 0

Jason
Jason

Reputation: 32490

and my other question is if i have a loop i.e how would insert all the integers i into (*it).first?

In the case of a std::map, you can't modify the iterator returned like that ... the key member (i.e., the first) in the std::map key/value pair data-structure is intentionally designated as a constant value, and is initialized to its constant value at the beginning of the key/value pair's lifetime in the std::map data-structure. If the keys weren't constant, you would end up creating havoc when you change the key, since the nodes in a std::map are suppose to be sorted by the keys. The second member of the key/value pair data-structure is the member that can be changed.

So if you want to insert a set of key/value pairs in a map, you could simply do the following:

std::map<int, int> mymap;
int some_other_value = 100;

for (int i=0; i < 10; i++)
{
    mymap[i] = some_other_value++;
}

Upvotes: 0

Shahbaz
Shahbaz

Reputation: 47493

The first part of your question:

std::vector<std::string> test;
std::vector<std::string> test2; // assuming map is from string to string
for (it = mymap.begin(); it != mymap.end(); ++it)
{
   test.push_back(it->first);     // push first in one vector
   test2.push_back(it->second);   // push second in another vector
}

So, yes a simple for can do what you want.


The second part of your question:

Since you are updating the key of the map, you would need to remove it from the map and insert the changed one. So:

std::string first, second;
first = it->first;
second = it->second;
mymap.erase(it);        // be careful with invalidating iterator
// change first
mymap[first] = second;

To change first by adding all integers i to it, that would really depend on the type of first. For example with a string, you may mean something like this:

ostringstream sout;
for (int i = 0; i < 10; ++i)
    sout << (i?" ":"") << i;
first = sout.str();

Or if first is for example a set, you may mean something like this:

for (int i = 0; i < 10; ++i)
    first.insert(i);

Upvotes: 0

Related Questions