Reputation: 101
I have a piece of code like this.
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
bool isInVecA(vector<A> vectorA, int iVal)
{
for(vector<A>::const_iterator it=vectorA.begin(); it != vectorA.end(); it++)
{
if(it->getVal() == iVal)
return true;
}
return false;
}
bool isInVecB(vector<B> vectorB, int iNum)
{
for(vector<B>::const_iterator it=vectorB.begin(); it != vectorB.end(); it++)
{
if(it->getNum() == iNum)
return true;
}
return false;
}
int main()
{
A arrayA[] = { A(1), A(2), A(3) };
vector<A> vectorA(arrayA, arrayA + sizeof(arrayA) / sizeof(A));
B arrayB[] = { B(3), B(4), B(5) };
vector<B> vectorB(arrayB, arrayB + sizeof(arrayB) / sizeof(B));
int key = 3;
if(isInVecA(vectorA, key) && isInVecB(vectorB, key))
cout << "Key " << key << " is in both vectors." << endl;
else
cout << "Key " << key << " is not in both vectors." << endl;
return 0;
}
What I want to do is just to create something to replace function isInVecA and isInVecB as they are too similar. Assume I cannot change class A and class B.
Thank you very much, everyone. I am quite new to StackOverflow. Not sure where to post a solution which my friend and I come up with. Therefore, I put it here.
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
#include <boost/bind.hpp>
using namespace std;
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
template<typename T>
bool isInVec(vector<T> vec, int (T::*func)() const, int iVal)
{
return find_if(vec.begin(), vec.end(), boost::bind(func, _1) == iVal) != vec.end();
}
int main()
{
A arrayA[] = { A(1), A(2), A(3) };
vector<A> vectorA(arrayA, arrayA + sizeof(arrayA) / sizeof(A));
B arrayB[] = { B(3), B(4), B(5) };
vector<B> vectorB(arrayB, arrayB + sizeof(arrayB) / sizeof(B));
int key = 3;
if(isInVec<A>(vectorA, &A::getVal, key) && isInVec<B>(vectorB, &B::getNum, key))
cout << "Key " << key << " is in both vectors." << endl;
else
cout << "Key " << key << " is not in both vectors." << endl;
return 0;
}
Upvotes: 0
Views: 180
Reputation: 24926
At some point you'll have to distinguish A
and B
(or more precisely getVal
and getNum
). For the search algorithm (as already mentioned) std::find_if
can be used with the predicates being Lambdas:
#include <algorithm>
// ...
int target = 5;
auto found_A = std::find_if(vectorA.begin(), vectorA.end(),
[target](A const &a) -> bool { return a.getVal() == target; });
auto found_B = std::find_if(vectorB.begin(), vectorB.end(),
[target](B const &b) -> bool { return b.getNum() == target; });
if (found_A != vectorA.end() && found_B != vectorB.end())
{
// target in vA and vB
// with found_A and found_B being valid iterators to the elements
}
Upvotes: 0
Reputation: 69854
#include <iostream>
#include <iterator>
#include <algorithm>
// class A and B unchanged, as requested
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
// new predicate to cover matching
struct matches
{
matches(int i) : _i(i) {};
bool operator()(const A& a) const {
return a.getVal() == _i;
}
bool operator()(const B& b) const {
return b.getNum() == _i;
}
int _i;
};
// convenience function to express the logic in a generic way
template<class Range>
bool contains(const Range& r, int key)
{
auto i = std::find_if(std::begin(r),
std::end(r),
matches(key));
return i != std::end(r);
}
// test
int main()
{
using namespace std;
A arrayA[] = { A(1), A(2), A(3) };
B arrayB[] = { B(3), B(4), B(5) };
int key = 3;
if (contains(arrayA, key) && contains(arrayB, key))
{
cout << "Key " << key << " is in both vectors." << endl;
}
else {
cout << "Key " << key << " is not in both vectors." << endl;
}
return 0;
}
Upvotes: 0
Reputation: 158
You have inconsistent interface between class A
and class B
. First make the interface common by introducing a new class class C
that inherits from class B
. Then create a templatized function isInVec
for comparision.
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
class C: public B
{
public:
C(int iNum) : B(iNum){}
int getVal() const { return getNum(); }
};
template <typename T>
bool isInVec(std::vector<T> vect, int iVal)
{
for(std::vector<T>::const_iterator it=vect.begin(); it != vect.end(); it++)
{
if(it->getVal() == iVal)
return true;
}
return false;
}
int main()
{
A arrayA[] = { A(1), A(2), A(3) };
std::vector<A> vecA(arrayA, arrayA + sizeof(arrayA) / sizeof(A));
C arrayC[] = { C(3), C(4), C(5) };
std::vector<C> vecC(arrayC, arrayC + sizeof(arrayC) / sizeof(C));
int key = 3;
if(isInVec(vecA, key) && isInVec(vecC, key))
std::cout << "Key " << key << " is in both vectors." << std::endl;
else
std::cout << "Key " << key << " is not in both vectors." << std::endl;
return 0;
}
Upvotes: 1
Reputation: 75062
You can create comparator and use std::find_if
.
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
class cmpA
{
private:
int target;
public:
cmpA(int t) : target(t) {}
bool operator()(const A& a) const {
return a.getVal() == target;
}
};
class cmpB
{
private:
int target;
public:
cmpB(int t) : target(t) {}
bool operator()(const B& b) const {
return b.getNum() == target;
}
};
template<class T, class V>
bool isInVec(const vector<V>& vector, int iNum)
{
return find_if(vector.begin(), vector.end(), T(iNum)) != vector.end();
}
int main(void) {
A arrayA[] = { A(1), A(2), A(3) };
vector<A> vectorA(arrayA, arrayA + sizeof(arrayA) / sizeof(A));
B arrayB[] = { B(3), B(4), B(5) };
vector<B> vectorB(arrayB, arrayB + sizeof(arrayB) / sizeof(B));
int key = 3;
if(isInVec<cmpA>(vectorA, key) && isInVec<cmpB>(vectorB, key))
cout << "Key " << key << " is in both vectors." << endl;
else
cout << "Key " << key << " is not in both vectors." << endl;
return 0;
}
UPDATE: New code with fewer similar code, which is based on the idea of Adapter Design Pattern:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class A
{
public:
A(int iVal) : _val(iVal) {}
int getVal() const { return _val; }
private:
int _val;
};
class B
{
public:
B(int iNum) : _num(iNum) {}
int getNum() const { return _num; }
private:
int _num;
};
// dummy number getter
template<class T> int getNumber(const T& x) { return 0; }
// number getter for class A
template<> int getNumber(const A& x) { return x.getVal(); }
// number getter for class B
template<> int getNumber(const B& x) { return x.getNum(); }
// comparator using the number getter
template<class T>
class cmp
{
private:
int target;
public:
cmp(int t) : target(t) {}
bool operator()(const T& a) const { return getNumber<T>(a) == target; }
};
template<class T>
bool isInVec(const vector<T>& vector, int iNum)
{
return find_if(vector.begin(), vector.end(), cmp<T>(iNum)) != vector.end();
}
int main(void) {
A arrayA[] = { A(1), A(2), A(3) };
vector<A> vectorA(arrayA, arrayA + sizeof(arrayA) / sizeof(A));
B arrayB[] = { B(3), B(4), B(5) };
vector<B> vectorB(arrayB, arrayB + sizeof(arrayB) / sizeof(B));
int key = 3;
if(isInVec(vectorA, key) && isInVec(vectorB, key))
cout << "Key " << key << " is in both vectors." << endl;
else
cout << "Key " << key << " is not in both vectors." << endl;
return 0;
}
Upvotes: 1
Reputation: 896
I wish I could reply to your question as a comment, but I do not have enough reputation to do so.
IF the vector is sorted then using "std::binary_search" is probably the fastest algorithm that you can use for searching a vector, but remember, the vector must be sorted.
You have to include the "algorithm" file in order to use the "binary_search" algorithm (which I see you have already done).
"binary_search" may or may not work for you, because you told us to assume that you cannot change either of the classes; if that is the case, you will not be able to implement the proper overloading of the "less than" operator if such action is needed.
Check out this link for a full description of the algorithm: http://www.cplusplus.com/reference/algorithm/binary_search/
Upvotes: 0