These iterator in the collection classes confuses me. I got a Map with key of string, and value being a Vector class (similar to an array). As i understand it my iterator variable it is assigned to the map. So i should be able to to get it´s value and assign it to a new Vector class so I can read it´s contents or know it´s size etc... but how do I do this?
for (Map<string, Vector<string> > :: iterator it = array0.begin();
it != array0.end(); it++)
{
Vector<string> arr = it; // Error
Assuming your Map is a std::map, the elements of a map are pairs of (key,value), so the value is the second element of the pair:
Vector<string> arr = it->second;
Related
Can I treat map key as pointer?
I have a struct which member is vector of strings, and I have a map
Is it possible to fill my vector with pointers to string1 ?
example
struct A
{
vector<string> v;
}
map<string, string> m;
m["hello"] = "test";
m["world"] = "test2";
A test;
for(map<string, string>::iterator it = m.begin(); it != m.end(); it++)
test.v.push_back(it->first)
can I do this?
does map key have an address that I can point to?
Yes, like all objects it has an address.
Can I treat map key as pointer?
No, it's not a pointer. But you can take its address.
Is it possible to fill my vector with pointers to string1 ?
No, because it's a vector of strings, not pointers; so you can fill it with copies of the map keys (as your code does), but not pointers. You could have a vector of pointers:
vector<string const *> v;
and fill that with pointers to the map keys:
test.v.push_back(&it->first);
If you remove any keys from the map, then make sure you don't try to use that pointer afterwards.
In a way, yes.
If you have a key stored somewhere, or read as input, then you can use it to search the map to see if if the key exists and get its value.
I have an unordered map that stores a string as its key and an iterator to a spot in a vector as its data. Each element in the vector holds a string and an int (number of times the string appears). I have coded an increaseCount(std::string, int) function that is supposed to insert the new string into the unordered map, unless it is already within the container. If this is the case, the function should find the key in the unordered map, got to the corresponding location in the vector that the iterator points to, and add one to the int parameter of the vector element. However, when executing the second case, the error "Vector iterator not dereferencable" shows up. Here is what I have coded.
void ourTrends::increaseCount(std::string s, unsigned int amount){
// check to see if key is already in
if(wordStoreTable.find(s) == wordStoreTable.end()){
// add the element into the hash table
std::vector<std::pair<std::string, int>>::iterator it;
std::pair<std::string, std::vector<std::pair<std::string, int>>::iterator> word (s, it);
wordStoreTable.insert(word);
// add element to back of vector
std::pair<std::string, int> p1 (s, amount);
sortedVector.push_back(p1);
//std::swap(sortedVector.front(), sortedVector.back());
// set the iterator of the hash pair to the end of the current vector size
it = sortedVector.end();
--it;
wordStoreTable.find(s)->second = it;
isSorted = false;
} else{
int x = wordStoreTable.find(s)->second->second;
std::pair<std::string, int> p1 (s, x + amount);
sortedVector.erase(wordStoreTable.find(s)->second);
sortedVector.push_back(p1);
//std::swap(sortedVector.begin(), sortedVector.end());
std::vector<std::pair<std::string, int>>::iterator it = sortedVector.end();
--it;
wordStoreTable.find(s)->second = it;
std::cout << wordStoreTable.find(s)->first << std::endl;
}
}
I know that this means the iterator is pointing to an empty location in memory, but I cannot figure out where it loses track of its destination.
The reason this code doesn't work, is that vector::push_back invalidates the iterators, that is, an iterator you had for a vector of size 3, might not work if you make the vector larger by adding a new element. From cppreference: If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.
You certainly could reserve enough space for the vector ahead of time, so that iterators do not invalidate, but as a general rule, you're better off with using numerical indices.
I am trying to create a map that contains a string key and an vector of myClass.
std::map<string,vector<myClass>> m;
I need to populate the vector as well and the map dynamically (reading values from a file).
class myClass{
string dataMember1;
...
myClass()
{ ... }
};
How should i proceed with it??
Also i want to be able to access the objects in the vector based on the string key.
for example:
std::map<string,vConnect>::iterator pos;
pos = mapGraph.find(string);
cout<<(pos->second)[0]->DataMemberofmyClass
will (pos->second)[0] indicate the first myClass object stored in the vector??
Thanks
Generally, when the mapped type is a container, just using []
everywhere works well; if the entry isn't present, it will be
created with an empty container, so things like:
m[key].push_back( newElement );
or
m[key].begin(), m[key].end()
or even:
if ( !m[key].empty() )
doSomethingWith( m[key].second[0] );
work correctly. If you're doing a number of operations on the
same element (as in the last two cases), you might want to hold
it in a reference:
std::vector<MyClass>& elem = m[key];
// ...
About the only exception would be if you're not modifying the
element, and you don't want to create the entry if it is empty.
In those cases, you'll need find, and a test:
std::map<std::string, std::vector<MyClass>>::const_iterator
entry = m.find( key );
if ( entry != m.end() ) {
std::vector<MyClass>& elem = entry->second;
// ...
}
Working with such nested types is not much different from working with simple map or vector. So an element of the map is a vector. Get this element and use it as a vector.
pos = mapGraph.find(string);
Returns an iterator in the map.
(pos->second)
Is the vector that is the value at this iterator. So simply use it as you would use a vector. Your code is correct apart from the fact you never check if an element was indeed found.
std::map<string,vConnect>::iterator pos;
pos = mapGraph.find(string);
if (pos != mapGraph.end()) {
cout<<(pos->second)[0].DataMemberofmyClass
}
EDIT(Thanks to us2012): in fact you had a small mistake (pos->second)[0] is an Object of MyClass so you access its members using . not using ->.
I dont understand what does that piece of code does
static TwoWayHostPair hostpair;
map <TwoWayHostPair, Traffic> mymap;
//here some map element inserted to mymap and hostpair initialized
map <TwoWayHostPair, Traffic>::iterator iter = mymap.begin();
iter = mymap.find(hostpair);
if (iter == mymap.end()) {
iter = mymap.insert(make_pair(hostPair, Traffic())).first; //line8
}
My question is what happens in line8? I didnt get it. Isnt it supposed to be type map<...>:iterator and after this insertion does it stay same type?
std::map::insert return std::pair< iterator,bool >, below statement is correct. second bool return value indicates whether the insertion took place
iter = mymap.insert(make_pair(hostPair, Traffic())).first; //line8
see reference here
As used here,
iter = mymap.insert(make_pair(hostPair, Traffic())).first; //line8
mymap.insert returns a pair<iterator,bool>. first, then, accesses the iterator.
insert(make_pair......
make_pair is used to insert pair value to a map.You have iterated for all the element in map having hostpair.
EDIT
Refer cplusplus map to know more.
iter = mymap.find(hostpair);
if (iter == mymap.end()) {
iter = mymap.insert(make_pair(hostPair, Traffic())).first; //line8
}
The first line looks for key hostPair in the map, and if it is not found, then it enters the if block where it inserts the key along with its value, and .first returns the iterator to the inserted item.
Improvement
But you can make an improvement to this. You could just write this:
iter = mymap.insert(make_pair(hostPair, Traffic())).first;
which is exactly equivalent to your code. No need to use find and then insert. The result is a performance gain.
If the key already exists, the insert function will NOT insert any item to the map and .first will return you the iterator to the found item. If the key doesn't exist, only then it will insert and .first will return you the iterator to the newly inserted item.
If you want to know whether the key already existed or not, then you can do this:
auto pair = mymap.insert(make_pair(hostPair, Traffic())); //NO .first!
if (pair.second)
{
//a newly created item is inserted
auto iter = pair.first; //iterator to the newly inserted item
}
else
{
//an item with key `hostPair` already exists in the map
auto iter = pair.first; //iterator to the found item
}
Hope that helps.
I've created a map of vectors that looks like this:
map<string, vector<char> > myMap;
string key = "myKey";
vector<char> myVector;
myMap[key] = myVector;
I want to be able to append 'char's' to the vector in the map but I can't figure out how to access said vector to append once the particular key/value(vector) has been created. Any suggestions? I'm iterating over char's and might be adding a lot to the vector as I go so it would be nice to have a simple way to do it. Thanks.
I would like the vector in map to be appended as I go. I don't need the original vector...I just need to return the map of key/vector's that I've created (after apending) so that I can pass it to another function. What does the * in map* > do? Is that refrencing a pointer? (I haven't gotten there in lecture yet) Also, do I need:
myMap[key]->push_back('s');
or
myMap[key].push_back('s');
??
To append:
myMap[key].push_back('c');
Or use myMap.find, but then you have to check whether you get an end iterator. operator[] returns a reference to the vector.
But this modifies the vector stored in the map, not the original one, since you've stored a copy in the map with myMap[key] = myVector;. If that's not what you want, you should rethink your design and maybe store (smart) pointers to vectors in your map.
Given you know the key:
string key = "something";
char ch = 'a'; // the character you want to append
map<string, vector<char> >::iterator itr = myMap.find(key);
if(itr != myMap.end())
{
vector<char> &v = itr->second;
v.push_back(ch);
}
you could also use the map::operator[] to access the map entry, but if the key does not exist, a new entry with that key will be created:
vector<char> &v = myMap[key]; // a map entry will be created if key does not exist
v.push_back(ch);
or simply:
myMap[key].push_back(ch);
To access the mapped value, which in your case is a vector, you just supply the key in square brackets like you did to assign the value.
So, to append 'a':
myMap[key].push_back('a');
I have an new suggestion. You can use vector<char>* instead of vector<char> in order to collect pointer of vectors in your map. For more information see the bellow code:
map<string, vector<char>* > myMap;
string key = "myKey";
vector<char>* myVector = new vector<char>();
myMap[key] = myVector;
myMap[key]->push_back('S');