Jannat Arora
Jannat Arora

Reputation: 2989

initialize 1000 map elements

Just as we can initialize vectors as:

  vector<int> var1(2000,1);

Is it possible to initialize map;

  map<int, int>var2;

for 2000 variables...the reason why I want to initialize are two:

  1. In case I access an element in future e.g. map[100]..I want that map[100]=0
  2. The second reason is that I am using a minimum priority queue which for comparison uses the second value of map i.e. the value stored in map[0]...map[100].
  3. I don't want to use vectors as my indices are really skewed and this leads to a lot of wasted space...i.e. my indices are map[0], map[30], map[56],map[100],map[120],map[190], etc.

Is there some way by which I can initialize the map for say 1000 variables...I am also open to using any other data structure.

Also the conventional way of initializing map i.e.

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

The above way does not work in my case...is there some other way out.PLEASE HELP

EDIT: I can not use for loop as:

This way the key remains fixed which I don't want since the distribution of my keys is skewed. In essence applying for loop in this way is the same as that of vector and this I don't want

Upvotes: 3

Views: 1684

Answers (5)

You don't need to do anything at all. When you use operator[] to access a key that was not previously inserted, a new value is created, initialized to 0 and a reference returned. There is no need to initialize at all.

Also nNote, that when you insert elements into the map, the key is fixed, so if you decide to insert 100 elements, the keys will be fixed, which will make initialization useless in most use cases.

I would avoid the complexity of initializing the map, and rather have a helper function that replaces operator[] as:

int &getValue( std::map<int,int>& m, int key ) {
    return *m.insert( std::make_pair(key,1) ).first;
}

There is no need to preallocate the nodes. The trick is that insert is equivalent to a lookup if the value already exists in the map, but will add the element if it was not present. Attempting an insert of a pair<int,int>(key,1) will insert 1 into the container if it did not exist before, but will leave the value untouched if it was already there. Because insert returns an iterator, we can use that to obtain a reference into the stored value.

The use would be just as simple as access through operator[]:

int x = getValue( mymap, 31 ); // 1 if 31 was not present in the map, else
                               // the value stored there.
getValue(mymap,31) = 5;        // Ugly, I know... but still simpler than providing
                               // an extra type, and preinitializing the container

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726509

You can do it using a surrogate instead of an int in your map, like this:

#include <iostream>
#include <map>

using namespace std;

struct surrogate_int {
    int val;
    surrogate_int() : val(1) {}
    surrogate_int& operator=(const int v) { val=v; }
    operator const int() { return val; }
};

int main() {
map<int,surrogate_int> m;
    m[5] = 5;
    m[7] = 7;
    m[9] = 9;
    for (int i = 0 ; i != 10 ; i++) {
        cout << i << ":" << m[i] << endl;
    }
return 0;
}

Upvotes: 1

skimon
skimon

Reputation: 1179

boost::assign:

///from http://www.boost.org/doc/libs/1_35_0/libs/assign/doc/index.html

#include <boost/assign/list_inserter.hpp> // for 'insert()'
#include <boost/assert.hpp> 
#include <string>
using namespace std;
using namespace boost::assign; // bring 'insert()' into scope

{
    map<string,int> months;  
    insert( months )
        ( "january",   31 )( "february", 28 )
        ( "march",     31 )( "april",    30 )
        ( "may",       31 )( "june",     30 )
        ( "july",      31 )( "august",   31 )
        ( "september", 30 )( "october",  31 )
        ( "november",  30 )( "december", 31 );
    BOOST_ASSERT( months.size() == 12 );
    BOOST_ASSERT( months["january"] == 31 );
} 

Upvotes: 0

bdow
bdow

Reputation: 181

You probably want to define your own data type that has an embedded priority (defaulting to 0, presumably), and define a comparator that uses that priority to order objects of your type. Something like

class MyType {
  int val;
  int priority;
  MyType(int val, int priority = 0): val(val), priority(priority) {}
  bool operator<(MyType const& other) { return priority < other.priority; }
}

Then you can just make a priority queue of that type, avoiding using a map at all.

Upvotes: 0

Attila
Attila

Reputation: 28762

You can do the old fashied way of using loops:

map<int, int> var2;
for (int = 0; i < 1000; ++i) {
  var2[i] = 0;
}

On the other hand usign the subscript notation (var2[x]) will add the value with its default value (0 for int) if the key does not exist in the map yet.

Upvotes: 0

Related Questions