2016-03-15 72 views
0

我有一块这样的代码。如何在矢量中查找物品?

#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; 
} 

我想要做的就是创造一些替换功能isInVecAisInVecB,因为他们太相似了。假设我不能变化A级B级


非常感谢大家。 我是StackOverflow的新手。不知道在哪里发布我的朋友和我提出的解决方案。所以,我把它放在这里。

#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; 
} 
+5

查看'std :: find_if'。 – Jarod42

回答

1

您可以创建比较器并使用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:用更少类似的代码,这是基于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; 
} 
+1

这并不删除OP提到的代码重复,它实际上需要更多类似的代码才能做到这一点。较短的版本将使用lambdas作为比较器。 – Ionut

+0

@Ionut我的新代码如何? – MikeCAT

0

我希望我能作为一个评论回复你的问题,但我不有足够的声誉来这样做。

IF矢量进行排序,然后使用“的std :: binary_search”可能是您可以使用搜索的载体,但要记住最快的算法,矢量必须进行排序。

您必须包含“算法”文件才能使用“binary_search”算法(我已经看到您已经完成)。

“binary_search”可能会也可能不会为你工作,因为你告诉我们假设你不能改变任何一个类;如果是这样的话,如果需要这样的操作,你将无法实现“小于”操作符的正确重载。

退房此链接算法的完整描述:http://www.cplusplus.com/reference/algorithm/binary_search/

+0

谢谢你的回答。该矢量并未在现实中排序。 – jiyi

+0

是的,没问题。我个人喜欢尽可能使用二分搜索,因为它们在很多情况下比线性搜索要快得多,但对排序数据的需求绝对是一个缺点。 – Fearnbuster

1

你有class Aclass B之间不一致的接口。首先通过引入一个继承自class B的新类class C来使接口通用。然后创建一个模板化函数isInVec进行比较。

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; 


} 
+0

谢谢你的回答。恐怕你的答案不能编译。 – jiyi

0
#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; 
} 
0

在某些时候你必须区分AB(或更精确地getValgetNum)。对于搜索算法(如已经提到的),std::find_if可以与谓词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 
}