Есть ли способ скопировать неконфликтующие значения карты с помощью std::copy?

Я ищу способ скопировать значения с одной карты на другую, подобно этот вопрос, но я не хочу, чтобы конфликтующие значения были перезаписаны второй картой, я хочу, чтобы исходные значения оставались нетронутыми.

Например, если бы у меня было две карты {a: 1, b: 2}, и я скопировал в них {b: 3, c: 4}, первая карта была бы изменена на {a: 1, b: 2, c: 4}.

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


person Alexis King    schedule 20.06.2013    source источник
comment
Вы могли бы использовать std::copy_if, но наверняка есть лучший подход для всего, что вы имеете в виду...   -  person K-ballo    schedule 20.06.2013
comment
@K-ballo но наверняка есть лучший подход для всего, что вы имеете в виду - Да, std::copy (без _if).   -  person Christian Rau    schedule 20.06.2013


Ответы (2)


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

#include <iostream>
#include <map>

int main() { 
    std::map<char, int> stuff;

    stuff['a'] = 1;
    stuff['b'] = 2;

    std::map<char, int> stuff2;

    stuff2['b'] = 3;
    stuff2['c'] = 4;

    stuff.insert(stuff2.begin(), stuff2.end());

    for (auto i : stuff)
        std::cout << i.first << "\t" << i.second << "\n";
}

Результат:

a       1
b       2
c       4
person Jerry Coffin    schedule 20.06.2013

Вы можете сделать это, используя std::for_each и лямбду:

std::map<int, int> m1 = ...;
std::map<int, int> m2 = ...;

std::for_each(m2.begin(), m2.end(),
             [&m1](const std::pair<const int, int>& a)
             {
                 if(m1.find(a.first) == m1.end())
                    m1.insert(a);
             });

По сути, это просто объединение того, что вам придется делать вручную, в std::for_each и лямбду. Насколько я знаю, на самом деле нет лучшего способа сделать то, чего вы хотите достичь.

Если ваш компилятор поддерживает emplace (чего нет в GCC 4.7, но поддерживает 4.8), вы можете использовать это:

std::for_each(m2.begin(), m2.end(),
             [&m1](const std::pair<const int, int>& a)
             {
                 m1.emplace(a.first, a.second);
             });

emplace сохранит элементы, создав новый элемент только в том случае, если предыдущий не существует.

person Yuushi    schedule 20.06.2013
comment
Насколько мне известно, нет лучшего способа добиться того, чего вы хотите достичь. – Помимо решения std::map::insert от Джерри, есть даже решение <algorithm›, которое намного проще, просто скопируйте его прямо на карту: std::copy(m2.begin(), m2.end(), std::inserter(m1, m1.end()));. std::map::insert автоматически оставляет существующие ключи такими, какие они есть. - person Christian Rau; 20.06.2013