george mano
george mano

Reputation: 6168

How can I fill a map of int and vector<int> in C++?

I have been working with <map>, where I declared a map as follows:

map <int, vector<int> > tree;

I am now trying to assign values to it. My goal is to place multiple values as elements of its keys. Something like this:

0=null
1=>0
2=>1,0
3=>2,1,0
4=>3,2,1,0
5=>0

I tried to assign to the map like this, but it does not work:

tree[3]=vector<int>(2,1,0);

However, the following two ways of assigning work:

tree[1]=vector<int>(0);
tree[2]=vector<int>(1,0);

Where is the problem? How can I make a function that works as a Python dictionary?

I am not using C++11.

Upvotes: 7

Views: 53477

Answers (7)

honk
honk

Reputation: 9743

Please note that the following two lines are not doing what you expect:

tree[1] = vector<int>(0);
tree[2] = vector<int>(1, 0);

The first parameter of the corresponding vector's constructor is the initial size of the container. The second parameter is the value to initialize elements of the container with. So, the first line constructs an empty vector and the second line constructs a vector with one element which is initialized to 0.

As indicated by the other answers, push_back() is a good option if you cannot use C++11 features. However, once you upgrade to C++11, you can also initialize your map by using nested list initialization as follows:

int main() {
    std::map<int, std::vector<int>> tree{
        {1, {0}}, {2, {1, 0}}, {3, {2, 1, 0}}, {4, { 3, 2, 1, 0 }}, {5, { 0 }}
    };

    for (auto const &kv : tree) {
        std::cout << kv.first << " =>";
        for (auto const &i : kv.second)
            std::cout << " " << i;
        std::cout << std::endl;
    }

    return 0;
}

Output:

1 => 0
2 => 1 0
3 => 2 1 0
4 => 3 2 1 0
5 => 0

Code on Ideone

Upvotes: 2

Drew Dormann
Drew Dormann

Reputation: 63745

Since you are asking for a C++03 answer, this (more verbose than C++11) solution will work.

tree[3].push_back(2);
tree[3].push_back(1);
tree[3].push_back(0);

Upvotes: 5

sehe
sehe

Reputation: 392911

Have you considered std::multi_map?

#include <map>

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

    for (int i=1; i < 6; i++)
        for (int j=1; j < i; j++)
            map.insert(std::make_pair(i, j));
}

Upvotes: 1

Rapptz
Rapptz

Reputation: 21317

I don't particularly like va_args but the solution is "neater" to a degree than most as long as you (the user) don't mess it up, i.e. mixing types. Another downside is that your vector cannot contain -1, but your example case doesn't show it.

#include <vector>
#include <cstdarg>
#include <iostream>

//Unsafe but it works.
template<typename T>
std::vector<T> make_vector(T num, ...) {
    std::vector<T> result;
    va_list args;
    va_start(args,num);
    for(T i = num; i != -1; i = va_arg(args,T))
        result.push_back(i);
    va_end(args);
    return result;
}

int main() {
    std::vector<int> v = make_vector(0,1,2,3,-1); //-1 to stop
    //do stuff with vector v
}

Upvotes: 0

Daniel Frey
Daniel Frey

Reputation: 56863

Without C++11, the code won't be as elegant:

tree[0]; // create empty vector for index 0
tree[1].push_back(0);
tree[2].push_back(1);
tree[2].push_back(0);
tree[3].push_back(2);
tree[3].push_back(1);
tree[3].push_back(0);
tree[4].push_back(3);
tree[4].push_back(2);
tree[4].push_back(1);
tree[4].push_back(0);
tree[5].push_back(0);

Upvotes: 1

Mr Fooz
Mr Fooz

Reputation: 111856

As Daniel Frey points out, you can use

tree[3] = vector<int>({2,1,0})

In python-like pseudo-code, the vector constructor being used here is

def vector(arr)

The original post suggests you're trying to use a constructor of the form

def vector(*args)

which doesn't exist.

If you're not using C++11, consider using one of vector's other constructors.

Upvotes: 0

Daniel Frey
Daniel Frey

Reputation: 56863

With C++11, you could try:

tree[3]=vector<int>({2,1,0});

Other than that, the question could use more details and some code of what you already tried...

Upvotes: 7

Related Questions