I did do a good search on the 'net about this and turned up lots of help regarding vectors but not really anything on STL lists. I am attempting to erase a pointer from a list within a map. (a little tricky). I really want to use pointers and not revert to another (worse) system of doing things. I will show the code
bool RoomDB::removePlayer( int socketid, int roomid ) {
list<GamePlayer>::iterator itit;
for( itit == roomlist[roomid].playerlist.begin(); itit != itit.end(); itit++ ) {
if( itit.socketno == socketid )
itit.erase( itit );
}
I think it should just be like this:
roomlist[roomid].playerlist.remove_if(
[socketid](GamePlayer const & gp) { return gp.socketno == socketid; }
);
If you don't have lambdas, you'll have to write a little predicate yourself, or you go the manual way; but now beware of the loop:
for (std::list<GamePlayer>::iterator it = roomlist[roomid].playerlist.begin();
it != roomlist[roomid].playerlist.end(); /* no increment */ )
{
if (it->socketno == socketid)
{
it = roomlist[roomid].playerlist.erase(it);
}
else
{
++it;
}
}
There are a bunch of things wrong. I will try to list all of them, though I may miss some:
It should be list<GamePlayer*>::iterator itit; if, as you say, your lists contain pointers
It should be itit = roomlist[roomid].playerlist.begin();, not itit = ..., like KerrekSB said
It should be itit != roomlist[roomid].playerlist.end(), not itit != itit.end()
It should be if( (*itit)->socketno == socketid ), not if( itit.socketno == socketid ) (again, if your list contains pointers)
It should be roomlist[roomid].playerlist.erase(itit), not itit.erase(itit).
Related
I have two lists which contain a bunch of elements of the same type:
std::list<Part> allParts = step.getSubParts();
std::list<Part> toRemove;
for (Part part : allParts)
{
for (Part partTwo : allParts) {
if (part.getEdges() == partTwo.getEdges())
if (part.getFaces() == partTwo.getFaces())
if (part.getShells() == partTwo.getShells())
if (part.getVertices() == partTwo.getVertices())
if (part.getWires() == partTwo.getWires())
{
part.addAmount(1);
toRemove.push_back(partTwo);
}
}
}
I have tried iterating through both and remove from the one but I'm constantly getting the list iterators are incompatible error. This is my latest attempt:
std::list<Part>::iterator it;
for (it = step.getSubParts().begin(); it != step.getSubParts().end();)
{
std::list<Part>::iterator i;
for (i = toRemove.begin(); i != toRemove.end();)
{
if (it->getEdges() == i->getEdges())
if (it->getFaces() == i->getFaces())
if (it->getShells() == i->getShells())
if (it->getVertices() == i->getVertices())
if (it->getWires() == i->getWires())
{
it = step.getSubParts().erase(it);
}
else
{
it++;
}
i++;
}
}
Everything I have tried doesn't work. What is the correct way to do this?
You should consider remove_if or erase_if rather than doing your own erase with the hazard of making iterator invalid within a loop.
By the way, you should write predicate like:
if (it->getEdges() == i->getEdges() &&
it->getFaces() == i->getFaces() &&
it->getShells() == i->getShells() &&
it->getVertices() == i->getVertices() &&
it->getWires() == i->getWires()) {
// do something
}
Your code makes people difficult to understand your purpose(at least me).
erase and erase_if
First of all, it would be a good idea to follow the Don't Repeat Yourself principle and write a comparison function for future use:
auto compare_parts = [](const Part& p1, const Part& p2) -> bool {
return ( (p1.getEdges() == p2.getEdges())
and (p1.getFaces() == p2.getFaces())
and (p1.getShells() == p2.getShells())
and (p1.getVertices() == p2.getVertices())
and (p1.getWires() == p2.getWires()) );
}
You would rewrite the first cycle using it and see how much more simple it looks.
Then why not use c++ built-in methods to erase the elements from the list using the function we wrote? This uses new feature in c++ called binding parameters that would aid us here
#include <functional>
using namespace std::placeholders;
for (auto&& badPart : toRemove) {
auto isBad = std::bind(compare_parts, badPart, _1);
step.getSubParts().remove_if(isBad);
}
And that's how you remove special entries from the list.
I think the cleanest way would be:
1. Implement equality operator for the class Part
You can either put it inside or outside the class, it would look like this if you implement it as an external function
inline bool operator==(const Part& lhs, const Part& rhs) {
return lhs.getEdges() == rhs.getEdges() &&
lhs.getFaces() == rhs.getFaces() &&
lhs.getShells() == rhs.getShells() &&
lhs.getVertices() == rhs.getVertices() &&
lhs.getWires() == rhs.getWires();
}
2. Implement the loop, I would recommend using iterators
This is just one way of doing it
if (allParts.size() > 1) {
for(auto partIt = std::begin(allParts); partIt != std::end(allParts); partIt++) {
for(auto partIt2 = std::next(partIt); partIt2 != std::end(allParts);) { // Manual increasing because we erase stuff
if(*partIt == *partIt2) { // Previously implemented equility operator
partIt->AddAmount(1);
partIt2 = allParts.erase(partIt2); // If erase, use the returned iterator as your next `Part`
} else {
partIt2++; // Only increment if nothing was erased (when you erase iterators get invalidated)
}
}
}
}
I need to write the following code in Scala (it is actually in C++). I have tried many ways but it still doesn't work. Any ideas?
pair<HashClosed::const_iterator, HashClosed::const_iterator> p =
closedItemsets.equal_range(pos1->second.myTidSum);
for ( HashClosed::const_iterator pos = p.first; pos != p.second; ++pos ) {
if ( pos->second.first == x->second.first ){}
Thx everyone , I have find the solution , this code in c++ is written as following in scala
for (pos <-pos.get(p._1) if pos != p._2)
{
pos._2.toMap
x._2.toMap
if(pos._1 == x._1)
{}
}
Using C++11, I'd like to iterate over a vector and return a type that indicates that the index was not found.
I am use to the traditional for(;;) loop and specifying the index manually, as my code shows below.
inline std::size_t ItemList::FindItem(Items& Item)
{
for (std::size_t i = 0; i < ItemVector.size(); i++)
{
if (ItemVector[i]->GetId() == Item.GetId() && !ItemVector[i]->GetName().compare(Item.GetName()))
{
return i + 1;
}
}
return 0;
}
I'm also having to increment the index +1 in order to return a value of 0 (to accommodate unsigned size_t) to indicate the calling method that the index was not found (I understand this is asinine). I am assuming it would be more suitable to return something more like std::end()?
Would using a C++11 iterator approach be more efficient? The vector will populate to a large number and the find needs to be quick.
You could use std::find_if and work with iterators:
auto it = std::find_if(ItemVector.begin(), ItemVector.end(),
[&Item](Items *value) {
return value->GetId() == Item.GetId() && !value->GetName().compare(Item.GetName());
}
);
Then you can simply test if it != ItemVector.end() to know if you found something.
There will likely be no (or very small) difference between this and your version in term of speed, but it is a cleaner way to check if something was found or not.
Yes, an iterator would be the way to do this, you're actually writing your own version of find_if You could instead do:
find_if(cbegin(ItemVector), cend(ItemVector), [&](const auto& i){ return i.GetId() == Item.GetId() && i.GetName() != Item.GetName(); })
You can test whether the result of this function was found by testing for equality with cend(ItemVector).
Additionally if you need to find the index of the item you can pass this result after cbegin(ItemVector) to: distance
Live Example
My solution for double search condition that Lambda has multiple parameters in find_if
bool check_second_loop(FullFrame *image_track, guint64 object_id, bool *deletion)
{
auto itr= std::find_if(image_track->track_ids.begin(),
image_track->track_ids.end(),
[object_id](const guint64& a)
{
return a == object_id;
});
if (itr != image_track->track_ids.end())
{
image_track->track_ids.erase(itr);
if(image_track->track_ids.size()==0)
{
*deletion = true;
}
return true;
}
else
return false;
}
bool check_first_loop(guint64 object_id, gint source_id)
{
bool deletion = false;
auto it = find_if(full_frame_list.begin(), full_frame_list.end(),
[object_id, &deletion, source_id](FullFrame &x)
{
return check_second_loop(&x, object_id, &deletion)
&& x.camera_number == source_id;
});
if (it != full_frame_list.end())
{
// Found
return true;
}
else
return false;
}
For example I have an vector of objects and they all have attribute PointX so I want to check if all of them have the same value of PointX and if they have it should return true or false whatever.
So in a kind of pseudo-code:
IF ( Object[1].getPointX() == Object[2].getPoint(x) == Object[3].getPoint(x) ){
return true;
}
The problem is that I have more than 55 objects so there has to be a way to compare them without writting them all individually. I know there must be with a for loop but still I have no idea.
thanks in advance.
edit:
#awesomeyi your suggestion seems the easiest and more adequate to my needs (I'm not saying the others are not but I think they are too complicated for a newb like me) but it's not working, even if Xpoints are all the same or different it always returns false. here's what i have:
bool allKilled(){
auto checkpointx = Invader[0].getIfActive();
for(int i = 0; i < 55; ++i){
if(Invader[i].getIfActive() != checkpointx){
return false;}
}
}
the getIfActive() just returns if its true or false, and i want this method to return true if all Active (attribute of the object) of all objects are all false.
Something like this:
auto refx = Object[0].getPointX();
bool b = std::all_of(Object.begin(),
Object.end(),
[refx](TheTypeOfTHeElements& e)
{ return e.getPointX() == ref; });
Obviously you need to check that Objects is not empty.
For loop?
auto checkpointx = Object[0].getPointX();
for(int i = 1; i < Object.size(); ++i){
if(Object[i].getPointX() != checkpointx)
return false;
}
I'd do it something like this:
template<typename Objects, typename Comparison>
bool is_all_same( Objects&& objects, Comparison&& comp ) {
using std::begin; using std::end;
auto&& b = begin(objects);
auto&& e = end(objects);
if (b == e)
return true;
auto&& first = *b;
for( auto&& cur = std::next(first); cur != e; ++cur ) {
if (!comp( first, cur ))
return false;
}
return true;
}
use:
bool all_same_x = is_all_same( objs, []( Obj const& left, Obj const& right )->bool {
return left.getPointX() == right.getPointX();
});
where objs is some container or range containing objects of type Obj.
The above code should work on all standard containers, C style arrays, custom containers that support the new for loops, and is close to optimal performance wise.
There are many functions within the code I am maintaining which have what could be described as boilerplate heavy. Here is the boilerplate pattern which is repeated ad nausea throughout the application when handling DB I/O with a cursor:
if( !RowValue( row, m_InferredTable->YearColumn(), m_InferredTable->YearName(), m_InferredTable->TableName(), value )
|| !IsValidValue( value ) )
{
GetNextRow( cursor, m_InferredTable );
continue;
}
else
{
value.ChangeType(VT_INT);
element.SetYear( value.intVal );
}
The thing is not all of these statements like this deal with ints, this "element" object, the "year" column, etc. I've been asked to look at condensing it even further than it already is and I can't think of a way to do it. I keep tripping over the continue statement and the accessors of the various classes.
Edit: Thanks to all those that commented. This is why I love this site. Here is an expanded view:
while( row != NULL )
{
Element element;
value.ClearToZero();
if( !GetRowValue( row, m_InferredTable->DayColumn(), m_InferredTable->DayName(), m_InferredTable->TableName(), value )
|| !IsValidValue( value ) )
{
GetNextRow( cursor, m_InferredTable );
continue;
}
else
{
value.ChangeType(VT_INT);
element.SetDay( value.intVal );
}
And things continue onward like this. Not all values taken from a "row" are ints. The last clause in the while loop is "GetNextRow."
Okay, from what you've said, you have a structure something like this:
while (row!=NULL) {
if (!x) {
GetNextRow();
continue;
}
else {
SetType(someType);
SetValue(someValue);
}
if (!y) {
GetNextRow();
continue;
}
else {
SetType(SomeOtherType);
SetValue(someOtherValue);
}
// ...
GetNextRow();
}
If that really is correct, I'd get rid of all the GetNextRow calls except for the last one. I'd then structure the code something like:
while (row != NULL) {
if (x) {
SetType(someType);
SetValue(someValue);
}
else if (y) {
SetType(someOtherType);
SetValue(SomeOtherValue);
}
// ...
GetNextRow();
}
Edit: Another possibility would be to write your code as a for loop:
for (;row!=NULL;GetNextRow()) {
if (!x)
continue;
SetTypeAndValue();
if (!y)
continue;
SetTypeandValue();
// ...
Since the call to GetNextRow is now part of the loop itself, we don't have to (explicitly) call it each time -- the loop itself will take care of that. The next step (if you have enough of these to make it worthwhile) would be to work on shortening the code to set the types and values. One possibility would be to use template specialization:
// We never use the base template -- it just throws to indicate a problem.
template <class T>
SetValue(T const &value) {
throw(something);
}
// Then we provide a template specialization for each type we really use:
template <>
SetValue<int>(int value) {
SetType(VT_INT);
SetValue(value);
}
template <>
SetValue<float>(float value) {
SetType(VT_FLOAT);
SetValue(value);
}
This lets you combine a pair of calls to set the type and the value into a single call.
Edit: As far as cutting processing short goes, it depends -- if parsing a column is expensive (enough to care about) you can simply nest your conditions:
if (x) {
SetTypeAndValue();
if (y) {
SetTypeAndValue();
if (z) {
SetTypeAndValue();
and so on. The major shortcoming of this is that it'll get pretty deeply nested if (as you've said) you have 20+ conditions in a single loop. That being the case, I'd probably think hard about the for-loop based version I gave above.
Why not make a function to do all the work?
bool processElement(Element& element, Row* row, int value, Table& m_InferredTable, /*other params*/)
{
if( !GetRowValue( row, m_InferredTable->DayColumn(), m_InferredTable->DayName(), m_InferredTable->TableName(), value )
|| !IsValidValue( value ) )
{
GetNextRow( cursor, m_InferredTable );
return true;
}
else
{
value.ChangeType(VT_INT);
element.SetDay( value.intVal );
}
return false;
}
In your loop
while (row != NULL)
{
if (processElement(element, row, value, m_InferredTable))
continue;
// other code
}
Why not invert your if-test?
if (RowValue(row, m_InferredTable->YearColumn(), m_InferredTable->YearName(), m_InferredTable->TableName(), value )
&& IsValidValue( value ))
{
value.ChangeType(VT_INT);
element.SetYear( value.intVal );
}
else
{
GetNextRow( cursor, m_InferredTable );
}
My instinctual approach is to build a polymorphic approach here, where you eventually wind up doing something like(modulo your language and exact logic):
db_cursor cursor;
while(cursor.valid())
{
if(cursor.data.valid())
{
process();
}
cursor.next();
}
db_cursor would be a base class that your different table type classes inherit from, and the child classes would implement the validity functions.
Move it into a template function, templated on the element type (e.g. integer), which you can call over and over. Vary the behavior per data type with a trait template.
template <typename T> struct ElemTrait<T> {};
template <> struct ElemTrait<int> {
static inline void set(Val &value, Elem &element) {
value.ChangeType(VT_INT);
element.SetYear(value.intVal);
}
};
// template <> struct ElemTrait<float> { ... };
template <typename T>
void do_stuff( ... ) {
// ...
if (!RowValue(row,
m_InferredTable->YearColumn(),
m_InferredTable->YearName(),
m_InferredTable->TableName(), value)
|| !IsValidValue(value)
) {
GetNextRow(cursor, m_InferredTable);
continue;
} else {
ElemTrait<T>::set(value, element);
}
// ...
}
You can take out all the GetNextRow calls and the else clauses:
for (row = GetFirstRow () ; row != null ; GetNextRow ())
{
Element element;
value.ClearToZero();
if( !GetRowValue( row, m_InferredTable->DayColumn(), m_MetInferredOutTable->DayName(), m_MetInferredOutTable->TableName(), value )
|| !IsValidValue( value ) )
{
continue;
}
value.ChangeType(VT_INT);
element.SetDay( value.intVal );
}