I'm iterating over my list of tuples : list<tuple<int,int>> edges
, and want to remove some elements in it. This is necessary for me to reduce the total overhead as I am working with huge data.
std::list<tuple<int, int>>::iterator it;
for (it = edges.begin(); it != edges.end(); it)
{
if (get<0>(*it) == 0 || get<1>(*it) == 0){
edges.remove(*it);
}
}
As I know, remove(element)
works, but here edges.remove(*it)
does not. How can I do this correctly?
CodePudding user response:
You can use erase()
to specify an element to remove by an iterator.
It returns an iterator for the next element, so don't forget to catch that.
std::list<tuple<int, int>>::iterator it;
for (it = edges.begin(); it != edges.end(); ) // don't increment it here
{
if (get<0>(*it) == 0 || get<1>(*it) == 0){
it = edges.erase(it);
} else {
it;
}
}
CodePudding user response:
In C 20, you can simply use a specialization of std::erase_if
for std::list
to do this.
#include <list>
#include <tuple>
int main() {
std::list<std::tuple<int, int>> l;
std::erase_if(l, [](const auto& elem) {
auto& [first, second] = elem;
return first == 0 || second == 0; });
}
However, since std::list
itself has a remove_if
member function, it is more appropriate to use it directly, since it applies to any C standard.
CodePudding user response:
In my opionion remove_if
which is a dedicated and optimized function for a std::list
should be used. This will avoid unnecessary indirections.
Please read here about it.
The result will be an efficient one liner.
Please see one of many potential solutions:
#include <iostream>
#include <list>
#include <tuple>
using MyTuple = std::tuple<int,int>;
using MyList = std::list<MyTuple>;
int main() {
// Define some demo data
MyList myList{{0,1},{2,3},{4,5},{6,0},{7,8},{9,10},{0,0}};
// Predicate function. Define whatever you want
auto unwanted = [](const MyTuple& t) {return std::get<0>(t)==0 or std::get<1>(t)==0;};
// Remove all unwanted stuff
myList.remove_if(unwanted);
// Some debug output
for (const auto&[l,r] : myList)
std::cout << l << ' ' << r << '\n';
}