Как поменять местами элементы карты

Как в C ++ поменять местами два элемента map?


person wrongusername    schedule 20.11.2010    source источник


Ответы (5)


Что вы имеете в виду под обменом на карте? Обычная простая ванильная карта не имеет какого-либо особого порядка, поэтому разговор об обмене не имеет значения в отношении порядка.

Если вы ищете реализацию карты C ++, которая сохраняет порядок, и в этом случае упорядочение становится значимым, посмотрите здесь

Однако, если вы хотите поменять местами значение, связанное с одним ключом, на значение, связанное со вторым ключом, просто выполните

  map<char,string> mymap;

  mymap['a']="firstValue";
  mymap['b']="SecondValue";
  /*now let's swap*/
  string tmpString = mymap['a'];
  mymap['a']=mymap['b'];
  mymap['b']= tmpString
person hhafez    schedule 20.11.2010
comment
Ах да, я забыл, что на самом деле нет порядка, связанного с картами ... спасибо, что указали на это! - person wrongusername; 20.11.2010
comment
std::map поддерживает отсортированный порядок, поэтому он реализован как самобалансирующееся двоичное дерево поиска. Возможно, вы перепутали его с std::unordered_map, который по сути представляет собой хеш-карту - без какого-либо определенного порядка. - person plasmacel; 31.10.2017

Предоставленные ответы верны, но используются operator[] дважды для одних и тех же ключей, что не является бесплатным, и этого можно было бы избежать:

std::map<char, std::string> a;

Решение 1:

std::string &item1 = a['a'];
std::string &item2 = a['b'];
std::swap(item1, item2);

Решение 2:

const std::map<char, std::string>::iterator item1 = a.find('a');
const std::map<char, std::string>::iterator item2 = a.find('b');
if ((item1 != a.end()) && (item2 != a.end()))
    std::swap(item1->second, item2->second);

Конечно, эти два решения не эквивалентны (решение 2 меняет местами только значения, которые уже есть на карте, решение 1 вставляет без вопросов и может закончиться заменой двух построенных по умолчанию строк).

person icecrime    schedule 20.11.2010
comment
Решение 1 безопасно? Я не могу найти ничего в документах STL, чтобы сказать, что ссылка на значение на карте не станет недействительной при вставке, хотя в g ++ она выглядит нормально. - person Pete Kirkham; 20.11.2010
comment
@Pete Я думаю, что это так, 23.1.2 / 8 Элементы вставки не должны влиять на действительность итераторов и ссылок на контейнер - person icecrime; 20.11.2010

Я считаю std::swap() хорошим выбором.

person Kylo    schedule 20.11.2010
comment
К сожалению, std::map<T>::iterator является константным итератором, не позволяющим пользователю изменять отсортированный порядок вне класса. Вы должны сначала отбросить const-ность с помощью const_cast, чтобы выполнить std::swap. - person plasmacel; 31.10.2017

Ни один из ответов, представленных до сих пор, не касается несуществующих ключей и сохранения несуществования этих ключей.

template<class Key, class Value>
void swap_map_elements(std::map<Key, Value>& map, const Key& key1, const Key& key2)
{
    auto it1 = map.find(key1);
    auto it2 = map.find(key2);
    auto end = map.end();

    if(it1 != end && it2 != end) {
        std::swap(it1->second, it2->second);
    }
    else if(it1 != end) {
        map.emplace(std::make_pair(key2, std::move(it1->second)));
        map.erase(key1);
    }
    else if(it2 != end) {
        map.emplace(std::make_pair(key1, std::move(it2->second)));
        map.erase(key2);
    }
}

Пример:

auto M = std::map<int, std::string>();
M.emplace(std::make_pair(1, "one"));
M.emplace(std::make_pair(2, "two"));

swap_map_elements(M, 1, 2); // 1: "two", 2: "one"
swap_map_elements(M, 1, 4); // 2: "one", 4: "two"
swap_map_elements(M, 5, 2); // 4: "two", 5: "one"
swap_map_elements(M, 8, 9); // 4: "two", 5: "one"
person Animiral    schedule 21.06.2016

Вы имеете в виду это?

const T tmp = map["a"];
map["a"] = map["b"];
map["b"] = tmp;
person Draco Ater    schedule 20.11.2010