Click here to Skip to main content
Licence CPOL
First Posted 10 May 2009
Views 11,395
Bookmarked 15 times

How To Update Your Const Key Fields in a Map/Multimap

By | 11 May 2009 | Article
An introduction to the necessary steps for updating const key fields in a map/multimap

Introduction

This is not a typical C++/STL article. Instead it is an observation which I faced in my professional programming life. The idea is simple, but the effect/impact is broad. Here I am going to provide a little utility that can take back a big effort while you are doing something same.

Background

What makes a Map/Multimap beautiful? Yes you guessed it right - A key-value field type container. If you have a look in the definition of STL Map/Multimap, you'll find something like this:

template <typename K, typename V,
          typename Compare = less<K>,
          typename Allocator = allocator<pair<const K, V> > >
class map; 

template <typename K, typename V,
          typename Compare = less<K>,
          typename Allocator = allocator<pair<const K, V> > >
class multimap;

So the definition looks pretty much the same, the only difference is Map never allows you to have duplicate keys, whereas Multimap allows.

Another observation/constraint is the Key field in a Map/Multimap is always constant. Once populated, you can't change/update the Key field in a conventional way, and there is a good reason behind this:

Because Map/Multimap sorts the elements based on their keys (along with the sorting functor (default is std::less, however you are free to change it to std::greater or your own functor) ) and assign the keys in a internal Red-black tree structure, if you or any generic algorithm updates the key field, that Red-Black tree will be invalid. The whole Tree might need to re-shuffle, which is quite a time consuming process. That is why STL designers takes the decision of:

You can't update the key field of a map/multimap in a conventional way.

You can't use map/multimap as a destination in a generic algorithm that updates the container.

But what if - you need to update your map/multimap's key field ? Sometimes it is damn necessary. Say initially you have a Multimap like this:

Key Value
Allen 100
Betty 200
Allen 200
Betty 300
John 500
Allen 900

Now you've to update the key "Allen" with "Gary". How will you do that?

You've only one choice left:

To modify the key of an element, you must remove the element that has the old key and insert a new element that has the new key and old value.

So, how can you do that by using a Generic Function?

Using the Code

Generic functions are good, specially when if you make it detachable from a container. In order to solve the above mentioned problem: my strategy is to write a generic function like this:

namespace My_Utility{
template <typename CONTAINER>
    void replace_key(CONTAINER& container,
                     const typename CONTAINER::key_type& oldKey,
                     const typename CONTAINER::key_type& newKey)
    {
        if(!container.key_comp()(oldKey,newKey) && !container.key_comp()(newKey,oldKey)){
	    return;} //Thanks to Graham for this Fix
        typename CONTAINER::iterator begin(container.find(oldKey));
        for(;;){
            if(begin != container.end()){
                container.insert(typename CONTAINER::value_type(newKey, begin->second));
                container.erase(begin); // Thanks to Graham for this potential fix
                begin = container.find(oldKey);
            }
            else{
                return;
            }
        }
    }
}

This is purely a Generic function. Given below is its description: 

  1. The template definition takes a single template parameter named CONTAINER (which can be either Map of Multimap).
  2. The argument list takes a Container, a const old key and a const new key, please see both the types of old key and newkey are fetched from the templated type. So this is purely generic.
  3. First check and return if Old key and New Key are equal, we don't need to update anything in that case. 
  4. If Old key and New key differ, then the function does as follows: 

    It finds the first iterator position where the old key exists, then it starts an infinite loop, which breaks when the iterator contains a value container.end(). Keep in mind that the find() algorithm returns cont.end() if it finds nothing, and returns the first iterator position when search is successful.

    If begin!=container.end(), then the function inserts a new row. Please see the code carefully.

    Then it erases the old row. Please see the code. It is:

    container.erase(begin);

    Then again a find() call.

Please use this code when you need to solve a similar kind of problem.  

History

  • 11th May, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

programmersmind

Software Developer (Senior)
Rebaca Technologies
India India

Member

int main(){
while(!isSleeping())
{
write_code();
}
return 0;
}

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 Pinmembermanoj kumar choubey18:01 28 Feb '12  
GeneralMy vote of 5 PinmemberRahul Rajat Singh19:15 17 Feb '12  
GeneralMy vote of 4 PinmemberJohn Schroedl5:09 18 May '11  
GeneralGreat artical Pinmembered welch2:23 12 Jun '09  
GeneralRe: Great artical Pingroupprogrammersmind8:21 13 Jun '09  
GeneralA couple of bugs PinPopularmemberGraham Shanks1:03 11 May '09  
GeneralRe: A couple of bugs Pinmemberprogrammersmind1:39 11 May '09  
GeneralRe: A couple of bugs PinmemberGraham Shanks2:46 11 May '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 11 May 2009
Article Copyright 2009 by programmersmind
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid