tags:

views:

640

answers:

3

I'd like to set all the values in a std::map to the same value.

Is there a method for this or do I have to iterate through the map and set them one by one?

+10  A: 

C++ has the fill method from <algorithm> but this doesn't work for maps. In fact, algorithm support for associative containers is generally not good.

As a result, you'll have to use an interation or write an appropriate functor to be used with for_each (but I consider this to be unnecessary overhead):

template <typename TKey, typename TValue>
struct resetter : public std::unary_function<std::pair<TKey, TValue> > {
    TValue const value;

    public resetter(value const& v) : value(v) { }

    public void operator ()(std::pair<TKey, TValue>& v) {
        v.second = value;
    }
};

for_each(map.begin(), map.end(), resetter<Key, Value>(value));
Konrad Rudolph
+2  A: 

The boost::assign library has all sorts of neat stuff to help out initializing the contents of a container. My thought that this could be used to avoid explicitly iterating through the map. Unfortunately, maps are curious beasts difficult to initialize because the keys must be unique. The bottom line is that a simple for loop is probably the best way to initialize a map. It may not be super elegant, but it gets the job done and is immediatly comprehensible by anyone with any acquaintance with the STL.

map <int,string> myMap;
for( int k=0;k<1000;k++)
  myMap.insert(pair<int,string>(k,string("")));

The rest of this post describes the journey I took to reach the above conclusion.

The boost::assign makes it simple to assign a small number of values to a map.

map<string,int> m; 
insert( m )( "Bar", 1 )( "Foo", 2 );

or

 map<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);

In your case, where you want to initialize the entire map with the same value, there are the utilities repeat and repeat_fun.
Something like this should work with a multimap ( untested code snippet )

pair<int,string> init( 0,string(""));
multimap <int,string> myMap = repeat(1000,init);

As Konrad Rudolph as pointed out, you cannot initialize a map with the same exact value, because the keys must be unique.

This makes life much more complex ( fun? ). Something like this, perhaps:

map <int,string> myMap;

struct nextkey
{
   int start;
   nextkey( s ) : start( s ) {}
   pair<int,string> operator () ()
{
   return pair<int,string>(start++,string(""));
}
};

myMap = repeat_fun(1000,nextkey(0));

Now, this is getting so complex, I now think a simple iteration IS the way to go

map <int,string> myMap;
for( int k=0;k<1000;k++)
  myMap.insert(pair<int,string>(k,string("")));
ravenspoint
Your code snippet won't work in a simple map because you insert the same key all over again. You have got to use a generator function in this case.
Konrad Rudolph
Good point! It would have to be a multimap, or use repeat_fun I wonder what the original question wanted?
ravenspoint
Yes Boost::assign is your easiest solution to filling maps. Totally agreed, besides the syntax is sleek almost script like.
Robert Gould
A: 

Why would you want to do this? Possibly a different data structure is required here?

Marcin