如何在向量中找到项目?

时间:2016-03-15 12:25:18

标签: c++ vector find

我有一段这样的代码。

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

我想做的只是创建一些东西来替换功能 isInVecA isInVecB ,因为它们太相似了。假设我不能更改 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 个答案:

答案 0 :(得分: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;
}

更新:代码较少的新代码,基于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 :(得分:1)

class Aclass B之间的界面不一致。首先通过引入从class C继承的新类class B来使界面通用。然后创建一个模板化的函数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;


}

答案 2 :(得分:0)

我希望我可以回复你的问题作为评论,但我没有足够的声誉这样做。

IF 对矢量进行排序,然后使用&#34; std :: binary_search&#34;可能是您可以用来搜索矢量的最快算法,但请记住,矢量必须进行排序。

你必须包含&#34;算法&#34;文件,以便使用&#34; binary_search&#34;算法(我看到你已经完成了)。

&#34; binary_search&#34;可能会或可能不会为你工作,因为你告诉我们假设你不能改变任何一个类;如果是这种情况,你将无法实现&#34;小于&#34;的正确重载。运营商,如果需要这样的行动。

查看此链接以获取算法的完整说明:http://www.cplusplus.com/reference/algorithm/binary_search/

答案 3 :(得分: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;
}

答案 4 :(得分:0)

在某些时候,您必须区分AB(或更准确地说getValgetNum)。对于搜索算法(如前所述),std::find_if可以与谓词Lambda一起使用:

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