removing duplicates from a c++ list - c++

I have been looking for an effective solution to remove duplicates from a C++ list.
The list consists of pointers to a class object which has an attribute ID. I want to remove duplicates based on that ID.
for my purpose, the unique method of the STL list will work in which we can pass a BinaryPredicate. i.e.
void unique( BinPred pr );
I searched on the internet about how to use this method, n got an example in which we can declare a function returning boolean and use the "name" of that function as Binary Predicate.
But it's not working.
What actually is this binary predicate and how do i use it ? ...
Any help will be appreciated.
Here is the code snippet:
class SP_MDI_View {
..
..
bool removeDupli(SP_DS_Node*, SP_DS_Node*);
bool DoReductionGSPN(SP_DS_Node*, SP_ListNode*, SP_DS_Node*);
..
..
}
SP_MDI_View::DoReduction( ... ) {
SP_ListNode setZ; // typedef list<SP_DS_Node*> SP_ListNode, where SP_DS_Node is some other class
setZ.clear();
setZ.merge(tempsubset);
setZ.merge(setX);
setZ.push_back(*cs_iter);
setZ.unique(removeDupli); //Error here
}
bool SP_MDI_View::removeDupli(SP_DS_Node* first, SP_DS_Node* second) {
return ( (first->GetId())==(second->GetId()) );
}

You could write a function like:
bool foo (int first, int second)
{ return (first)==(second) ); }
Also, you might need to declare the function as static if your using it in class.

You have to use unique on an ordered list. So the first thing that you must do is sort the list.

Related

C++ CppCheck algorithm suggestion (std::find_if instead of raw loop) pertinence

CppCheck suggest me to replace one of my code by a STL algorithm, I'm not against it, but I don't know how to replace it. I'm pretty sure this is a bad suggestion (There is warning about experimental functionalities in CppCheck).
Here is the code :
/* Cutted beginning of the function ... */
for ( const auto & program : m_programs )
{
if ( program->compare(vertexShader, tesselationControlShader, tesselationEvaluationShader, geometryShader, fragmentShader) )
{
TraceInfo(Classname, "A program has been found matching every shaders.");
return program;
}
}
return nullptr;
} /* End of the function */
And near the if condition I got : "Consider using std::find_if algorithm instead of a raw loop."
I tried to use it, but I can't get the return working anymore... Should I ignore this suggestion ?
I suppose you may need to use that finding function not once. So, according to DRY, you need to separate the block where you invoke an std::find_if algorithm to a distinct wrapper function.
{
// ... function beginning
auto found = std::find_if(m_programs.cbegin(), m_programs.cend(),
[&](const auto& prog)
{
bool b = prog->compare(...);
if (b)
TraceInfo(...);
return b;
});
if (found == m_programs.cend())
return nullptr;
return *found;
}
The suggestion is good. An STL algorithm migth be able to choose an appropriate
approach based on your container type.
Furthermore, I suggest you to use a self-balancing container like an std::set.
// I don't know what kind of a pointer you use.
using pProgType = std::shared_pointer<ProgType>;
bool compare_progs(const pProgType &a, const pProgType &b)
{
return std::less(*a, *b);
}
std::set<std::shared_pointer<prog_type>,
std::integral_constant<decltype(&compare_progs), &compare_progs>> progs.
This is a sorted container, so you will spend less time for searching a program by a value, given you implement a compare operator (which is invoked by std::less).
If you can use an stl function, use it. This way you will not have to remember what you invented, because stl is properly documented and safe to use.

Construct lists from existing lists at compile time

I have a global list of items (each with a few properties) in a module of my program. It's immutable and statically defined in the code, so no worries there.
For instance let's say I have vegetables, which are just an alias defining them to an immutable tuple with name (string), code (ubyte) and price (ushort).
I'd like to be able to access those either by name or by code ; so I thought since the list of vegetables is known at compile-time, I could probably construct associative arrays with references to these vegetables (so string=>vegetable and ubyte=>vegetable)
Here's the kind of thing I am trying to achieve :
static struct instructions
{
// list of Veggies
immutable instr[] list = [
Veggie("Potato" , 0xD0, 2),
Veggie("Carrot" , 0xFE, 5),
];
// genByCode and genByName being pure functions that get CTFE'd
// and return the desired associative array
immutable instr[ubyte] byCode = genByCode(list);
immutable instr[string] byName = genByName(list);
// overloaded function returns the right Veggie
instr get(string name) const
{ return byName[name]; }
instr get(ubyte code) const
{ return byCode[code]; }
}
With those generator functions (separated for clarity) of the form
pure instr[ubyte] genByCode(immutable Veggie[] list)
{
instr[ubyte] res;
foreach (i ; list)
res[i.code] = i;
return res;
}
I spent quite some time messing around but I couldn't it to work. Of course it would be trivial to construct at runtime, but clearly it should be possible to do it at compile time.
At first I thought it was an issue of mutability, so I tried marking everything (vegetables and vegetable lists) as immutable (as they should be anyway), but then I ran into issues which I think regard immutable tuples, and feel too lost to keep going.
Could I get help from someone with a clearer overview of the mechanisms at play here ? Thanks !
The data is already there, no need to construct a compile-time associative array.
Just iterate over it statically:
static auto get(int code)(){
static foreach(veggie; list)
static if(veggie.code == code)
return veggie;
}
...
void main(){
writeln(instructions.get!0xD0);
}
It may be slower than access through a hash map, but that's the life of CTFE.
To make sure it evaluates at compile time, you can use this:
template get(int code){
static foreach(veggie; list)
static if(veggie.code == code)
alias get = veggie;
}

C++, how to call functions when reading their ID number from a Mysql table?

I have a Mysql table that I am using as a list of different calculations that needs to be done.
Each line in the table has a column of type INT that has the number of the function that needs to be called.
e.g. line 6, data, (function) 1.
I read all the lines one by one and I need to call the relevant functions for each line.
What is the best way to construct it in C++?
should I have another function that returns the pointer of the functions that needs to be called ?
Are there other recommended solutions?
Thanks
It depends on the type of the function (input/outputs) but assuming they are all the same, you can make an array of function pointers. For example:
std::vector<void(*)(int)> MyArray;
Will declare an array of function pointers returning void and taking one int as parameter. Then you can put the functions you want in it and when you want to call them you can use MyArray[i]
If the actual type for the function pointer is long and hard to type, you can use decltype(MyFunction) instead. This requires C++11 though.
Using function pointers may work may work but I would rather make use of something like Strategy pattern.
class DataProcessor {
public:
virtual void process(Data& data) = 0;
// some other things like dtors etc
}
For each type of "function" you can create its corresponding DataProcessor.
To ease lookup, you may make use of a factory, or simply a std::map<int, DataProcessor> (instead of using int as key, will you consider using an enum?), or even a vector/array of DataProcessor.
As a suggestion, this is another way:
//Create only a function and make a switch statement in it:
void myfunction (std::pair<int,int> aRow) { // function:
int result;
int data = aRow.second;
int function_id = aRow.second;
switch(function_id){
case 1:{
//Funcion with any signature
break;
}
case 2:{
//Funcion with another signature
break;
}
//and so on...
}
//do something with the result...
}
int main () {
//Fetch your mysql data here:
std::vector<std::pair<int, int> > myMySQLdata;
for_each (myMySQLdata.begin(), myMySQLdata.end(), myfunction);
}

Proper implementation of removing vector elements

ALL,
It's continuation of this thread.
What I tried is to write following code:
struct Remover : public std::binary_function<CPlayer,void,bool>
{
public:
bool operator()(const CPlayer &player) const
{
return player.IsNewPlayer();
}
};
and call it this way:
players_pool->erase( std::remove_if( players_pool->begin(), players_pool->end(), std::bind2nd( Remover() ) ) );
but it gives me an error:
std::bind2nd(): expects 2 arguments - 1 provided.
How do I properly call this functor?
Thank you.
You don't need to wrap Remover() in std::bind2nd().
Also, you don't need to derive from std::binary_function<> (which is wrong, anyway; Remover is a unary functor). You don't need to derive from anything, in fact.
Finally, if your compiler supports C++11, you can reduce your code down to this:
players_pool->erase( std::remove_if( begin(*players_pool), end(*players_pool),
[](const CPlayer &player) {
return player.IsNewPlayer();
} ),
end(*players_pool) );
Just change your binary_function to a unary_function.
You also need to add the end iterator to the erase call, in order to erase all removed values.

Easy way to check if item is in list?

I'm writing a search algorithm in C++, and one of the things I need to do is have a few if statements that check cells above, below, left of, and right of.
Each time a cell is found to be open and added to the stack, I want it added to a list of cells already checked.
I want to be able to say in the if statement if(thisCell is not in checkedCells).
Any simple ideas?
For this purpose it's better to use the std::set container, because it provides you with the ability to search for items faster than a list. Then you can write:
std::set<itemType> myset;
...
if (myset.find(item) != myset.end()) {
// item is found
}
A larger example can be found by googling. For example, here.
If the number of items are in the hundreds, you can use simple, sequential search. This algorithm is built-into C++ as the find() function:
#include <algorithm> // for find()
typedef std::vector<Cell> CellList;
CellList checked_cells;
// .....
Cell cellToSearch;
if (is_in_checked_cells (cellToSearch, cells))
{
// .....
}
// Makes a sequential search using find().
static bool
is_in_checked_cells (const Cell &cell, const CellList &cells)
{
CellList::const_iterator end = cells.end ();
CellList::const_iterator item = std::find (cells.begin (), end, cell);
return (item != end);
}
Make sure Cell has operator< overridden.
If the list is very large, you may want to use binary search, which also comes bundled with C++:
#include <algorithm> // for sort() and binary_search()
CellList checked_cells;
// Make sure the cells are sorted.
checked_cells.sort (checked_cells.begin (), checked_cells.end ());
Cell cellToSearch;
if (is_in_checked_cells (cellToSearch, cells))
{
// .....
}
// Searches using binary_search().
static bool
is_in_checked_cells (const Cell &cell, const CellList &cells)
{
return std::binary_search (cells.begin (), cells.end (), cell);
}