I have a map that links a size_t to a pair, of size_t and int
std::map< size_type, std::pair<size_t, unsigned int> > mapVals;
essentially my understanding of this, is that maps work similar to stacks, and jst insert one after another, giving something similar to:
1 -> (2,2)
2 -> (4,7)
3 -> (8,5)
etc.
my question is, how do I obtain the value of the int. i.e. 2,7,5. I want to use this value as the max size of a while loop.
Maps are not similar to stacks; a stack maintains a first-in-last-out (FILO) strategy. A map is something that maps a key to a value.
If you do something like:
typedef std::pair<size_t,unsigned_int> my_pair;
// Insert elements
my_map[3] = my_pair(2,2);
my_map[9] = my_pair(4,7);
my_map[7] = my_pair(8,5);
You can retrieve the second element of your pair as:
my_map[9].second // evaluates to 7
To access the int you can do one of two things
unsigned int myint = mymap[key].second;
where key is of type size_t. This works because using [size_t] on the map returns a std::pair<size_t, unsigned int> then calling .second on this gets you the uint.
You could also use iterators
std::map<size_t, std::pair<size_t, unsigned int> >::iterator itr = mymap.begin(); // say
unsigned int myint = itr->second.second;
typedef std::map< size_type, std::pair<size_t, unsigned int> > mymapT;
mymapT mapVals;
... // fill the map
first = mapVals[1].second;
second = mapVals[2].second;
third = mapVals[3].second;
... // do something useful
You can do something like this:
typedef std::map< size_type, std::pair<size_t, unsigned int> > myMap;
myMap mapVals;
// ... populate
myVals[1] = std::pair<size_t, unsigned int>(2,2);
// ...
for (myMap::const_iterator it = myVals.begin(); it != myVals.end(); ++it)
unsigned int each_value = it->second.second;
The first it->second will give you the std::pair <size_t, unsigned int> element. The second second will give you the unsigned int contained in that pair.
I'm not sure what you want exactly
for (std::map< size_type, std::pair<size_t, unsigned int> >::iterator it = mapVals.begin(); it != mapVals.end() ; it++)
cout << it->second.first << " " << it->second.second << endl;
it->second : is the Value part of the map (in this case std::pair<size_t, unsigned int>)
it->second.second : is the second part of the pair (unsigned int)
Related
I have the following map:
std::map<char, std::pair<int, int> > robots;
I am using this function to populate the map given the input meets certain conditions:
bool World::addRobot(int row, int col, char robot_name) {
// This if block checks if the desired location is a valid 1 and keeps a track of all the robots already in the grid
if (map_[row][col] == '1' && robots.find(robot_name) == robots.end()){
map_[row][col] = robot_name;
robots.insert(make_pair(robot_name, std::make_pair(row, col)));
}
else{std::cout << "Invalid input" << std::endl;}
return true;
}
Each robot name, which is just a single char, is saved with a pair of its location, which are just row/col coordinates. In the following function, I want to be able to retrieve & ethe location pairs given the robot name:
std::pair<int, int> World::getRobot(char robot_name) {
std::pair<int, int> location = robots.find(robot_name);
return location;
}
But the name location is redlines with the following error message:
No viable conversion from 'std::map<char, std::pair<int, int>>::iterator' (aka '_Rb_tree_iterator<std::pair<const char, std::pair<int, int>>>') to 'std::pair<int, int>'
Where am I going wrong? How can I return the coordinate pairs from just the robot name?
An iterator for a map "points to" a std::pair<const KEY, VALUE>.
For your map, the KEY is char and the VALUE is std::pair<int, int>
So in your code, instead of:
std::pair<int, int> location = robots.find(robot_name);
you need to:
std::pair<int, int> location = robots.find(robot_name)->second;
Also, you need to check and see if the call to find fails to find the key you want. In that case the iterator will be equal to robots.end, and you'll have to deal with that:
const auto it = robots.find(robot_name);
if (it != robots.end()) {
return it->second;
} else {
// Not found, do something else
}
std::map::find returns a map iterator which is a "logical pointer" to a std::pair of key and value of the element in the map (not only the value).
The second member of this pair is the value that you seek to return from getRobot (which is by itself a pair of ints).
Fixed version:
std::pair<int, int> World::getRobot(char robot_name)
{
auto it = robots.find(robot_name);
if (it == robots.end())
{
return std::pair<int, int>(0, 0); // return some default value
}
return it->second;
}
2 additional notes:
I used auto which is very convenient when using iterators (instead of specifying the long iterator type).
I added a check whether the key is in the map. If not - return some default value. You can change the default value, or change the method prototype to return an error status in this case.
I am trying to learn boost mpl, tried a very simple example to count the number of times a type appears in mpl map. Could somebody explain why the output of this program is 0
typedef map<
pair<int, unsigned>
, pair<char, unsigned char>
, pair<long_<5>, char[17]>
, pair<int[42], bool>
> m;
std::cout << mpl::count <
m,
mpl::key_type
<
m,
pair<int, unsigned>
>::type
>::type::value << std::endl;
According to what is written in the code you'd like to count the occurrences of type
key_type<
m,
pair<int, unsigned>
>::type
in your map. In the end this is an int because in the description of mpl::key_type you'll find:
key_type<m,x>::type Identical to x::first;
Well, so let's see what are the actual contents of your map.
I could just write the type of the map, but I'd like to show you how to check a type the quick and lazy way. :P
So, we just make the compiler fail to see whats the type of the map.
I did it with adding this line somewhere:
typename m::blaa BB;
The compilation of course fails (because blaa is not an element of the mpl::map type) with following error message:
error: 'blaa' in 'm {aka struct boost::mpl::map<boost::mpl::pair<int, unsigned int>, boost::mpl::pair<char, unsigned char>, boost::mpl::pair<mpl_::long_<5l>, char [17]>, boost::mpl::pair<int [42], bool> >}' does not name a type
Ok, what we can read is that the map contains a list of pairs (e.g., boost::mpl::pair<int, unsigned int>),
but no int. And in your mpl::count call you are looking for int.
Just try to replace your std::cout lines with
the following lines and you'll see that the result will be as expected.
std::cout <<
boost::mpl::count< m,
boost::mpl::pair<int, unsigned>
>::type::value
<< std::endl;
I have a loop, which is calculating the size of second member of the p,
where p is std::pair<const std::string, std::set<std::string>>
for (const auto& p : ref)
std::cout << p.second.size() << endl;
Now I want to create another map cnt (std::map<std::string, int> cnt;),
which saves p.first and p.second.size() after every iteration.
How can I do that?
Declare std::map<std::string, int> cnt;
Before you iterate through whatever data structure you are using to store the pairs. While you are iterating though this structure, simply put
cnt[p.first] = p.second.size();
I'm using std::multimap in this way
std::multimap<float, std::pair<int, int> > edges;
I want to sort it by the first float number, but later count how many int (the first one of <int, int>) are in this multimap.
for example,
I have element pairs (0.6001, <2,3>), (0.62, <2,4>), (0.63, <1,3>) in my multimap,
I want to count the number of <2,*> (it should be 2 here).
Is there a simpler way (something like edges.count()) than to get every element out and count?
Or is there another container that I could turn to?
#
Solution 1
I'll first store the values I need to count in a std::set and count as codes given by jrok or johny;
Solution 2
I'll use a std::multimap to store the second and third element again and count.
Thank you both jrok and johny!
What about this?
std::multimap<float, std::pair<int, int> > edges;
typedef std::multimap<float, std::pair<int, int> >::value_type ElemT;
int value = 2;
int count =
std::count_if(edges.begin(), edges.end(),
[value](const ElemT& e) { return e.second.first == value; });
I would like to search within a vector<std::pair<int, vector<int> > >. This won't work due to the vector parameters:
std::vector<std::pair<int, std::vector<int> > > myVec;
iterator = find(myVec.begin(), myVec.end(), i);
Search would be on the first std::pair template parameter (int), in order to get the vector associated with it.
std::vector<std::pair<int, std::vector<int> > > myVec;
This requires C++0x for the lambda expression:
typedef std::pair<int, std::vector<int>> pair_type
std::find_if(myVec.begin(), myVec.end(), [i](pair_type const& pair)
{ return pair.first == i; });
If you're not using C++0x then either roll out your own loop or use something like Boost.Phoenix/Boost.Lambda.
Or, for both cases, why not use std::map?
You could make do with the following (pretty ugly) functoid:
struct FindFirst {
FindFirst(int i) : toFind(i) { }
int toFind;
bool operator()
( const std::pair<int, std::vector<int> > &p ) {
return p.first==toFind;
}
};
using it like this ( I couldn't get bind2nd to work - that's why I used the c'tor ):
int valueToFind = 4;
std::find_if(myVec.begin(), myVec.end(), FindFirst(valueToFind));
I think what you would like is a map:
std::map< int, vector< int > > foo;
You can then add elements, search by key etc:
int key = 4; //This will be the key
vector<int> value(5, 4); //Fill some values (5 4's in this case) into the vector
foo[key]=value; //Adds the pair to the map. Alternatively;
foo.insert( make_pair(key, value) ); //Does the same thing (in this context)
Looking at the way you've done things though, you might be wanting a std::multimap (which allows multiple values to have the same key) Class docs here
You're trying to map an int to a vector of int.
So try map<int, vector<int> >.
The second template parameter of a vector is the allocator - your compiler can probably puzzle out what you wanted to say, the declaration is wrong anyway. What you probably want is some sort of map type, like iammilind suggested.