I have a map std::map<int, std::vector<Data>>myMap and my structure is defined as follows.
struct Data
{
int x;
int z;
int y;
};
in myMap key is int and value is vector of structure
I'm given with x and key value.
I want remove the object from the vector where the key and x value of the vector object matches
I have tried by giving all the x,y,z values of the structure :
myMap[123].erase(std::remove(myMap[123].begin(), myMap[123].end(), {1,2,3}), myMap[priority].end());
But Here only X value will be given.
I have tried to write a function as follows :
void deleteByx(int x)
{
for (std::map<int,std::vector<Data>>::iterator it = myMap.begin(); it != myMap.end(); it++)
{
std::vector<Data> list = it->second;
for (std::vector<Data>::iterator vec_it = list.begin(); vec_it != list.end(); vec_it++)
for(int index = 0;index < list.size();index++)
{
if (vec_it->x == x)
{
list.erase(vec_it);
}
}
}
}
but here the function deletes the element from the local vector list
If you want to have access to the actual data item, then you need to get a reference to that item. Instead, your current code gets a copy of the vector.
Thus this line:
std::vector<Data> list = it->second;
Should be:
std::vector<Data>& list = it->second;
Thanks for the time. I have tried with the following code and it worked for me.
for ( itr = myMap[key].begin(); itr != myMap[key].end(); ++itr)
{
if (itr->x == 1)
{
myMap[key].erase(itr);
break;
}
}
Related
How to insert result into a new multimap?? I am trying to search over dictionary container to find keyword given by the user and I need to iterate over the tempCollector to find distinct elements. But, I can't seem to find a way to store the results in tempCollector.
//current container with all the data
multimap<string, DictionaryItem> dictionaryContainer;
void search(vector<string> input) {
if (dictionaryContainer.empty()) {
cout << "it's empty";
}
int inputSize = input.size();
string tempKeyword = input[0];
//need to copy or insert the value and keys to the tempCollector
multimap<string, DictionaryItem>tempCollector;
//iteration to find keyword; want to store the result in tempCollector
auto its = dictionaryContainer.equal_range(tempKeyword);
for (multimap<string, DictionaryItem>::iterator itr =its.first; itr != its.second; itr++) {
itr->second.print();
}
};
If you want to copy the whole its range:
tempCollector.insert(its.first, its.second);
If you want to copy each element:
for (auto itr =its.first; itr != its.second; itr++) {
if (condition) {
tempCollector.emplace(tempKeyword, itr->second);
//or
tempCollector.insert(*itr);
//or
tempCollector.emplace(tempKeyWord, DictionaryItem(...));
}
}
Keep in mind (multi)map handles pairs of key/values as std::pair<Key,T> (aka value_type).
The multimap::insert method assumes you've already constructed the pair(s) to insert, while multimap::emplace will build them for you.
I have a map which contains a of vector of type Messages.
std::map<std::string, std::vector<Message>> storage;
class Message has 3 member variables.
class Message
{
private:
std::string msg;
std::string msg_type;
int priority;
}
Now i am trying to delete an object which has priority(say 3) from the map. i am using the following function for it. But it doesn't work.
void deleteByMessagePriority(int priority)
{
if (checkPriorityOfMessage(priority))
{
for (std::map<std::string, std::vector<Message>>::iterator it = storage.begin(); it != storage.end(); it++)
{
std::vector<Message> listOfMsgs = it->second;
for (std::vector<Message>::iterator vec_it = listOfMsgs.begin(); vec_it != listOfMsgs.end(); vec_it++)
//for(int index = 0;index < listOfMsgs.size();index++)
{
if (vec_it->getPriority() == priority)
{
listOfMsgs.pop_back();
}
}
}
}
}
Look carefully at this:
if (vec_it->getPriority() == priority)
{
listOfMsgs.pop_back();
}
You're looking at the priority of one message (the one referred to by vec_it), but then what are you deleting if it matches?
Instead of writing your own loop, I'd use erase and std::remove_if to remove all the items you care about in that vector at once.
for (auto & item : storage) {
auto &vec = item.second;
auto start_junk = std::remove_if(
vec.begin(), vec.end(),
[=](Message const &m) { return m.priority == priority; });
vec.erase(start_junk, vec.end());
}
if (vec_it->getPriority() == priority)
{
listOfMsgs.pop_back();
pop_back() removes the last element of the vector which you don't want.You want to check erase
Also remember erase() invalidates the iterators so you need iterator to the next element after a deleted element for which we can fortunately use return value of erase
if (vec_it->getPriority() == priority)
{
vec_it = listOfMsgs.erase(vec_it); //returns iterator to the element after vec_it which can also be `listOfMsgs.end()`
std::vector<Message> listOfMsgs = it->second;
.
.
.
listOfMsgs.pop_back();
You're copying the list, only to modify the copy. What you meant is:
std::vector<Message>& listOfMsgs = it->second;
Then you can proceed erasing elements. As Gaurav Sehgal says, use the return value of erase:
std::vector<Message>::iterator vec_it = listOfMsgs.begin();
while (vec_it != listOfMsgs.end())
{
if (vec_it->getPriority() == priority)
{
vec_it = listOfMsgs.erase(vec_it);
}
else
{
++vec_it;
}
}
I have a list of vector of Data (object) and I need to iterate through the list, find the biggest vector, remove it from the list and assign it to a new variable (which is a vector of Data). I am having problems during execution (it compiles ok but then stops working). How can I get the element without destroying it so I can manipulate later?
This is the code:
int biggestIndex = 0, biggestValue = -1;
i = 0;
list< vector<Data> >::iterator it;
for (it = (myList).begin(); it!= (myList).end(); it++) {
if ((*it).size() > biggerSize) {
biggestIndex = i;
biggestValue = basePList.size();
}
i++;
}
it = (myList).begin();
advance(it,biggestIndex);
vector<Data> partition = (vector<Data>) *it;
auto biggest = thelist.begin();
for (auto itr = thelist.begin() ; itr != thelist.end(); itr++) {
if (itr->size() > biggest->size()) {
biggest = itr;
}
}
vector<int> thebiggest = *biggest;
This of course needs to be compiled with at least C++11 extensions enabled, so add -std=c++11 or higher to your g++ command.
auto longest = *max_element(begin(myList),
end(myList),
[](const vector<Data>& v1, const vector<Data>& v2)
{return v1.size() < v2.size();});
I am currently programming a little game for the console with an 2D map. 2 Elements of my game are: destroying fields and an enemy, which spreads in a random direction (its getting bigger). These two "entities" are saved in a structure which contains two vectors (X and Y). I am now trying to erase an element of "_Enemy"(<-private instance of the structure in a class, same as "_DestroyedFields") if you destroy the field where the enemy is.
I tried a lot of different variations to do so and whats giving me the error least is this method (I already searched the internet for a while now an couldn't find a answer to my question):
for (std::vector<int>::iterator itEX = _Enemys.X.begin(), itEY = _Enemys.Y.begin();
itEX != _Enemys.X.end() && itEY != _Enemys.Y.end();
++itEX, ++itEY) {
for (std::vector<int>::iterator itX = _DestroyedFields.X.begin(),
itY = _DestroyedFields.Y.begin();
itX != _DestroyedFields.X.end() && itY != _DestroyedFields.Y.end();
++itX, ++itY) {
if (*itY == *itEY && *itX == *itEX){
itEY = _Enemys.Y.erase(itEY);
itEX = _Enemys.X.erase(itEX);
}
}
}
PS: sorry if my english isn't the best, im german ^^
PSS: if you wanna watch over my whole code, you can find it on Github: https://github.com/Aemmel/ConsoleGame1
After erasing using iterator it, you cannot use it further as it is invalidated. You should use a result of a call to erase which is new, valid iterator.
for( it = v.begin(); it != v.end();)
{
//...
if(...)
{
it = v.erase( it);
}
else
{
++it;
}
...
}
I fixed the bug with first: making a "simple structure"(struct Entity{int X; intY} and then std::vector [insert name here]) and then with adding an break; if the condition is true.
for (Uint itE = 0; itE < _Enemys.size(); ++itE){
for (Uint it = 0; it<_DestroyedFields.size(); ++it){
if (_Enemys.at(itE).Y == _DestroyedFields.at(it).Y
&& _Enemys.at(itE).X == _DestroyedFields.at(it).X){
_Enemys.erase(_Enemys.begin()+itE);
break;
}
}
}
With struct Position {int x; int y;}; and some utility operators,
you may do one of the following: (https://ideone.com/0aiih0)
void filter(std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
for (std::vector<Position>::iterator it = positions.begin(); it != positions.end(); ) {
if (std::find(destroyedFields.begin(), destroyedFields.end(), *it) != destroyedFields.end()) {
it = positions.erase(it);
} else {
++it;
}
}
}
Or, if input are sorted, you may use a 'difference':
std::vector<Position> filter2(const std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
std::vector<Position> res;
std::set_difference(positions.begin(), positions.end(),
destroyedFields.begin(), destroyedFields.end(),
std::back_inserter(res));
return res;
}
I have a std::map object as follows
typedef std::map<int,int> RoutingTable;
RoutingTable rtable;
and then I've initialized it in a function
for (int i=0; i<getNumNodes(); i++)
{
int gateIndex = parentModuleGate->getIndex();
int address = topo->getNode(i)->getModule()->par("address");
rtable[address] = gateIndex;
}
Now I want to change the values in the rtable in another function. how can I achieve this?
Pass the rtable by reference:
void some_func(std::map<int, int>& a_rtable)
{
// Either iterate over each entry in the map and
// perform some modification to its values.
for (std::map<int, int>::iterator i = a_rtable.begin();
i != a_rtable.end();
i++)
{
i->second = ...;
}
// Or just directly access the necessary values for
// modification.
a_rtable[0] = ...; // Note this would add entry for '0' if one
// did not exist so you could use
// std::map::find() (or similar) to avoid new
// entry creation.
std::map<int, int>::iterator i = a_rtable.find(5);
if (i != a_rtable.end())
{
i->second = ...;
}
}