How do I merge two maps in STL and apply a function for conflicts?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite












I have read the Merge two STL maps question, and though it's close I was looking for functionality like the one described here.



In short, I would like to have merge two std::map instances (having thee same key and value type) into one, with the caveat that I would like to add the values together if the object exists in both maps.



Is there an existing boost, range-v3, or std function that can do this? And if not, what would be the best way to achieve it?



Example code:



double mergePredicate(double lhs, double rhs)

return lhs + rhs;


int main()

std::map<int, double> mapA = 0, 1.0, 1, 2.0 ;
std::map<int, double> mapB = 1, 1.5, 2, 2.5 ;

// Merge maps in some way...
mapA.merge(mapB, mergePredicate);

std::cout << mapA << std::endl;
// result: mapA == 0, 1.0, 1, 3.5, 2, 2.5

return 0;










share|improve this question























  • Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
    – David Marabottini
    24 mins ago














up vote
6
down vote

favorite












I have read the Merge two STL maps question, and though it's close I was looking for functionality like the one described here.



In short, I would like to have merge two std::map instances (having thee same key and value type) into one, with the caveat that I would like to add the values together if the object exists in both maps.



Is there an existing boost, range-v3, or std function that can do this? And if not, what would be the best way to achieve it?



Example code:



double mergePredicate(double lhs, double rhs)

return lhs + rhs;


int main()

std::map<int, double> mapA = 0, 1.0, 1, 2.0 ;
std::map<int, double> mapB = 1, 1.5, 2, 2.5 ;

// Merge maps in some way...
mapA.merge(mapB, mergePredicate);

std::cout << mapA << std::endl;
// result: mapA == 0, 1.0, 1, 3.5, 2, 2.5

return 0;










share|improve this question























  • Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
    – David Marabottini
    24 mins ago












up vote
6
down vote

favorite









up vote
6
down vote

favorite











I have read the Merge two STL maps question, and though it's close I was looking for functionality like the one described here.



In short, I would like to have merge two std::map instances (having thee same key and value type) into one, with the caveat that I would like to add the values together if the object exists in both maps.



Is there an existing boost, range-v3, or std function that can do this? And if not, what would be the best way to achieve it?



Example code:



double mergePredicate(double lhs, double rhs)

return lhs + rhs;


int main()

std::map<int, double> mapA = 0, 1.0, 1, 2.0 ;
std::map<int, double> mapB = 1, 1.5, 2, 2.5 ;

// Merge maps in some way...
mapA.merge(mapB, mergePredicate);

std::cout << mapA << std::endl;
// result: mapA == 0, 1.0, 1, 3.5, 2, 2.5

return 0;










share|improve this question















I have read the Merge two STL maps question, and though it's close I was looking for functionality like the one described here.



In short, I would like to have merge two std::map instances (having thee same key and value type) into one, with the caveat that I would like to add the values together if the object exists in both maps.



Is there an existing boost, range-v3, or std function that can do this? And if not, what would be the best way to achieve it?



Example code:



double mergePredicate(double lhs, double rhs)

return lhs + rhs;


int main()

std::map<int, double> mapA = 0, 1.0, 1, 2.0 ;
std::map<int, double> mapB = 1, 1.5, 2, 2.5 ;

// Merge maps in some way...
mapA.merge(mapB, mergePredicate);

std::cout << mapA << std::endl;
// result: mapA == 0, 1.0, 1, 3.5, 2, 2.5

return 0;







c++ merge stdmap






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 mins ago









Jarod42

110k1299175




110k1299175










asked 39 mins ago









nonsensickle

2,93311949




2,93311949











  • Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
    – David Marabottini
    24 mins ago
















  • Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
    – David Marabottini
    24 mins ago















Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
– David Marabottini
24 mins ago




Have you thought to see if the Algorythm library of c++ has the matching algorythm, because, I think could be here, now I don't use the c++, but I studied it and I remember thhat the algorythm library hase some algorythm of common use, the sort, the swap and this algorythm are templetizing
– David Marabottini
24 mins ago












3 Answers
3






active

oldest

votes

















up vote
4
down vote













I don't know of any existing function to do this, but if you don't mind tearing apart the map you're merging from, you can make use of std::map's merge function (live example):



template<typename K, typename V, typename F>
void mergeWithConflicts(std::map<K, V>& base, std::map<K, V>& toMerge, F combine)
base.merge(toMerge);

// All that's left in toMerge is conflicting keys
for (const auto& [k, v] : toMerge)
base[k] = combine(base[k], toMerge[k]);




As a bonus, the implementation of merge is rather efficient compared to what you can do by hand unless you reimplement it using the likes of extract. Instead of copying or moving elements, it adjusts internal pointers to move nodes from one map to the other.






share|improve this answer


















  • 2




    Note that complexity is O(N log N).
    – Jarod42
    12 mins ago










  • @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
    – chris
    7 mins ago

















up vote
3
down vote













I don't know of any existing function for that, but you can roll your own from something similar to std::merge implementation to have linear complexity:



template<class Map, class Merger>
void merge(Map& dest, const Map& source, Merger merger)

auto it1 = dest.begin();
auto it2 = source.begin();
auto&& comp = dest.value_comp();

for (; it1 != dest.end() && it2 != source.end(); )
if (comp(*it1, *it2))
++it1;
else if (comp(*it2, *it1))
dest.insert(it1, *it2);
++it2;
else // equivalent
it1->second = merger(it1->second, it2->second);
++it1;
++it2;


dest.insert(it2, source.end());



Demo






share|improve this answer





























    up vote
    2
    down vote













    For this specific case, because operator creates a key if it doesn't exist, you can use simple loop to add the two values:



    for (auto pair : mapB) 
    mapA[pair.first] += pair.second;



    And when you want to use a function, but it is okay to use a default-initialized value where no key exists:



    for (auto pair : mapB) 
    mapA[pair.first] = mergePredicate(mapA[pair.first], pair.second);






    share|improve this answer


















    • 1




      Note that complexity is O(N log N).
      – Jarod42
      12 mins ago










    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53205898%2fhow-do-i-merge-two-maps-in-stl-and-apply-a-function-for-conflicts%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote













    I don't know of any existing function to do this, but if you don't mind tearing apart the map you're merging from, you can make use of std::map's merge function (live example):



    template<typename K, typename V, typename F>
    void mergeWithConflicts(std::map<K, V>& base, std::map<K, V>& toMerge, F combine)
    base.merge(toMerge);

    // All that's left in toMerge is conflicting keys
    for (const auto& [k, v] : toMerge)
    base[k] = combine(base[k], toMerge[k]);




    As a bonus, the implementation of merge is rather efficient compared to what you can do by hand unless you reimplement it using the likes of extract. Instead of copying or moving elements, it adjusts internal pointers to move nodes from one map to the other.






    share|improve this answer


















    • 2




      Note that complexity is O(N log N).
      – Jarod42
      12 mins ago










    • @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
      – chris
      7 mins ago














    up vote
    4
    down vote













    I don't know of any existing function to do this, but if you don't mind tearing apart the map you're merging from, you can make use of std::map's merge function (live example):



    template<typename K, typename V, typename F>
    void mergeWithConflicts(std::map<K, V>& base, std::map<K, V>& toMerge, F combine)
    base.merge(toMerge);

    // All that's left in toMerge is conflicting keys
    for (const auto& [k, v] : toMerge)
    base[k] = combine(base[k], toMerge[k]);




    As a bonus, the implementation of merge is rather efficient compared to what you can do by hand unless you reimplement it using the likes of extract. Instead of copying or moving elements, it adjusts internal pointers to move nodes from one map to the other.






    share|improve this answer


















    • 2




      Note that complexity is O(N log N).
      – Jarod42
      12 mins ago










    • @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
      – chris
      7 mins ago












    up vote
    4
    down vote










    up vote
    4
    down vote









    I don't know of any existing function to do this, but if you don't mind tearing apart the map you're merging from, you can make use of std::map's merge function (live example):



    template<typename K, typename V, typename F>
    void mergeWithConflicts(std::map<K, V>& base, std::map<K, V>& toMerge, F combine)
    base.merge(toMerge);

    // All that's left in toMerge is conflicting keys
    for (const auto& [k, v] : toMerge)
    base[k] = combine(base[k], toMerge[k]);




    As a bonus, the implementation of merge is rather efficient compared to what you can do by hand unless you reimplement it using the likes of extract. Instead of copying or moving elements, it adjusts internal pointers to move nodes from one map to the other.






    share|improve this answer














    I don't know of any existing function to do this, but if you don't mind tearing apart the map you're merging from, you can make use of std::map's merge function (live example):



    template<typename K, typename V, typename F>
    void mergeWithConflicts(std::map<K, V>& base, std::map<K, V>& toMerge, F combine)
    base.merge(toMerge);

    // All that's left in toMerge is conflicting keys
    for (const auto& [k, v] : toMerge)
    base[k] = combine(base[k], toMerge[k]);




    As a bonus, the implementation of merge is rather efficient compared to what you can do by hand unless you reimplement it using the likes of extract. Instead of copying or moving elements, it adjusts internal pointers to move nodes from one map to the other.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 14 mins ago

























    answered 25 mins ago









    chris

    45k9104163




    45k9104163







    • 2




      Note that complexity is O(N log N).
      – Jarod42
      12 mins ago










    • @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
      – chris
      7 mins ago












    • 2




      Note that complexity is O(N log N).
      – Jarod42
      12 mins ago










    • @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
      – chris
      7 mins ago







    2




    2




    Note that complexity is O(N log N).
    – Jarod42
    12 mins ago




    Note that complexity is O(N log N).
    – Jarod42
    12 mins ago












    @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
    – chris
    7 mins ago




    @Jarod42, Fair point. It depends what the expectations are in terms of conflicts vs. map size. I believe your linear approach could be made to have the same benefits rearranging nodes as well, though I'd say the tradeoff between that and this version is in code complexity.
    – chris
    7 mins ago












    up vote
    3
    down vote













    I don't know of any existing function for that, but you can roll your own from something similar to std::merge implementation to have linear complexity:



    template<class Map, class Merger>
    void merge(Map& dest, const Map& source, Merger merger)

    auto it1 = dest.begin();
    auto it2 = source.begin();
    auto&& comp = dest.value_comp();

    for (; it1 != dest.end() && it2 != source.end(); )
    if (comp(*it1, *it2))
    ++it1;
    else if (comp(*it2, *it1))
    dest.insert(it1, *it2);
    ++it2;
    else // equivalent
    it1->second = merger(it1->second, it2->second);
    ++it1;
    ++it2;


    dest.insert(it2, source.end());



    Demo






    share|improve this answer


























      up vote
      3
      down vote













      I don't know of any existing function for that, but you can roll your own from something similar to std::merge implementation to have linear complexity:



      template<class Map, class Merger>
      void merge(Map& dest, const Map& source, Merger merger)

      auto it1 = dest.begin();
      auto it2 = source.begin();
      auto&& comp = dest.value_comp();

      for (; it1 != dest.end() && it2 != source.end(); )
      if (comp(*it1, *it2))
      ++it1;
      else if (comp(*it2, *it1))
      dest.insert(it1, *it2);
      ++it2;
      else // equivalent
      it1->second = merger(it1->second, it2->second);
      ++it1;
      ++it2;


      dest.insert(it2, source.end());



      Demo






      share|improve this answer
























        up vote
        3
        down vote










        up vote
        3
        down vote









        I don't know of any existing function for that, but you can roll your own from something similar to std::merge implementation to have linear complexity:



        template<class Map, class Merger>
        void merge(Map& dest, const Map& source, Merger merger)

        auto it1 = dest.begin();
        auto it2 = source.begin();
        auto&& comp = dest.value_comp();

        for (; it1 != dest.end() && it2 != source.end(); )
        if (comp(*it1, *it2))
        ++it1;
        else if (comp(*it2, *it1))
        dest.insert(it1, *it2);
        ++it2;
        else // equivalent
        it1->second = merger(it1->second, it2->second);
        ++it1;
        ++it2;


        dest.insert(it2, source.end());



        Demo






        share|improve this answer














        I don't know of any existing function for that, but you can roll your own from something similar to std::merge implementation to have linear complexity:



        template<class Map, class Merger>
        void merge(Map& dest, const Map& source, Merger merger)

        auto it1 = dest.begin();
        auto it2 = source.begin();
        auto&& comp = dest.value_comp();

        for (; it1 != dest.end() && it2 != source.end(); )
        if (comp(*it1, *it2))
        ++it1;
        else if (comp(*it2, *it1))
        dest.insert(it1, *it2);
        ++it2;
        else // equivalent
        it1->second = merger(it1->second, it2->second);
        ++it1;
        ++it2;


        dest.insert(it2, source.end());



        Demo







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 11 mins ago

























        answered 17 mins ago









        Jarod42

        110k1299175




        110k1299175




















            up vote
            2
            down vote













            For this specific case, because operator creates a key if it doesn't exist, you can use simple loop to add the two values:



            for (auto pair : mapB) 
            mapA[pair.first] += pair.second;



            And when you want to use a function, but it is okay to use a default-initialized value where no key exists:



            for (auto pair : mapB) 
            mapA[pair.first] = mergePredicate(mapA[pair.first], pair.second);






            share|improve this answer


















            • 1




              Note that complexity is O(N log N).
              – Jarod42
              12 mins ago














            up vote
            2
            down vote













            For this specific case, because operator creates a key if it doesn't exist, you can use simple loop to add the two values:



            for (auto pair : mapB) 
            mapA[pair.first] += pair.second;



            And when you want to use a function, but it is okay to use a default-initialized value where no key exists:



            for (auto pair : mapB) 
            mapA[pair.first] = mergePredicate(mapA[pair.first], pair.second);






            share|improve this answer


















            • 1




              Note that complexity is O(N log N).
              – Jarod42
              12 mins ago












            up vote
            2
            down vote










            up vote
            2
            down vote









            For this specific case, because operator creates a key if it doesn't exist, you can use simple loop to add the two values:



            for (auto pair : mapB) 
            mapA[pair.first] += pair.second;



            And when you want to use a function, but it is okay to use a default-initialized value where no key exists:



            for (auto pair : mapB) 
            mapA[pair.first] = mergePredicate(mapA[pair.first], pair.second);






            share|improve this answer














            For this specific case, because operator creates a key if it doesn't exist, you can use simple loop to add the two values:



            for (auto pair : mapB) 
            mapA[pair.first] += pair.second;



            And when you want to use a function, but it is okay to use a default-initialized value where no key exists:



            for (auto pair : mapB) 
            mapA[pair.first] = mergePredicate(mapA[pair.first], pair.second);







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 25 mins ago

























            answered 31 mins ago









            Ville-Valtteri

            3,69711637




            3,69711637







            • 1




              Note that complexity is O(N log N).
              – Jarod42
              12 mins ago












            • 1




              Note that complexity is O(N log N).
              – Jarod42
              12 mins ago







            1




            1




            Note that complexity is O(N log N).
            – Jarod42
            12 mins ago




            Note that complexity is O(N log N).
            – Jarod42
            12 mins ago

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53205898%2fhow-do-i-merge-two-maps-in-stl-and-apply-a-function-for-conflicts%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            List of Gilmore Girls characters

            What does second last employer means? [closed]

            One-line joke