Копирование карты C ++ в векторы ключей и значений - PullRequest
5 голосов
/ 28 марта 2012

У меня есть map, и я хочу, чтобы первый столбец i.e (*it).first был перенесен обратно в вектор, а (*it)->second - в другой вектор

Это лучший способ сделать это?

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

Мой другой вопрос, если у меня есть цикл, то есть как мне вставить все целые числа i в (*it).first?

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

Я хочу иметь несколько целых чиселв (*it).first и имеют связанные значения в (*it).second;

Ответы [ 8 ]

5 голосов
/ 28 марта 2012

Использование std::transform.

Сначала определите две функции key и value, которые принимают пару строк и возвращают первое или второе значение соответственно.

#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;
}

Затем используйте std::transform из <algorithm> с функциями для преобразования карты в vector клавиш или vector значений.

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;
}

Выход:

Keys:
alice
bob

Values:
555-2701
555-2702
2 голосов
/ 28 марта 2012

Ваш первый вопрос, «как я могу вставить первый столбец моей карты в один вектор, а второй столбец в другой», решается следующим образом:

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);
}

Ваш второй вопрос: «Как бы вставить все целые числа i в (*it).first?» решается так:

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];
}

или

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);
}
2 голосов
/ 28 марта 2012

Ну, это можно сделать с помощью простого цикла:

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

Или используя алгоритм std::transform, хотя здесь он довольно многословен:

std::transform(mymap.begin(), mymap.end(), std::back_inserter(vec1),
               [](MyMap::const_reference p) { return p.first; });
1 голос
/ 28 марта 2012

Если вы объявили свою карту как строковый ключ и значение (т. Е. map<string, string> mymap;, тогда это будет так, как показано ниже, также предполагается, что вы объявили переменную 'it' как map<string, string>::iterator it и т. Д .:

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);
}

Не уверен насчет вашего следующего вопроса.

0 голосов
/ 28 марта 2012

На всякий случай, если вы хотите иметь дело с различными типами данных на вашей карте, я бы назначил общую функцию копирования:

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 );   
    }

}

Смешивание:

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);

Редактировать: да __copy не лучшее определение. Спасибо

0 голосов
/ 28 марта 2012

здесь будет итератор, который будет указывать на одну из позиций на карте, и в максимуме будет иметь одно первое и второе значение для одного итератора.При макс. У вас может быть несколько клавиш или одна и та же клавиша, содержащая одни и те же / разные значения в зависимости от комбинации ключ / значение.

Что касается нажатия значения вектора для ключа на карте, вы можете сделать это вТочно так же, как вы нажимаете клавишу

     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);


     }

Сегодня ваш вопрос очень неясен.

0 голосов
/ 28 марта 2012

Первая часть вашего вопроса:

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
}

Итак, да, простой for может делать то, что вы хотите.


Вторая часть вашего вопроса:

Поскольку вы обновляете ключ карты, вам необходимо удалить его с карты и вставить измененный.Итак:

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

Чтобы изменить first, добавив к нему все целые числа i, это действительно будет зависеть от типа first.Например, со строкой вы можете означать что-то вроде этого:

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

Или, если первым является, например, set, вы можете означать что-то вродеэто:

for (int i = 0; i < 10; ++i)
    first.insert(i);
0 голосов
/ 28 марта 2012

, и другой мой вопрос, если у меня есть цикл, то есть как вставить все целые числа i в (* it) .first?

В случае std::map,Вы не можете изменить итератор, возвращенный таким образом ... ключевой элемент (т. е. первый) в структуре данных пары ключ / значение std::map преднамеренно обозначается как постоянное значение и инициализируется его постоянным значением вначало времени жизни пары ключ / значение в структуре данных std::map.Если бы ключи не были постоянными, вы бы в конечном итоге создали хаос при смене ключа, так как предполагается, что узлы в std::map отсортированы по ключам.Второй элемент структуры данных пары ключ / значение - это элемент, который можно изменить.

Поэтому, если вы хотите вставить набор пар ключ / значение в карту, вы можете просто сделать следующее:

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

for (int i=0; i < 10; i++)
{
    mymap[i] = some_other_value++;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...