如何在向量中查找项

How to find an item in a vector?

本文关键字:查找 向量      更新时间:2023-10-16

我有一段这样的代码。

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

我想做的只是创建一些东西来替换函数是InVecAisInVecB,因为它们太相似了。假设我不能更改类 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;
}

您可以创建比较器并使用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;
}

更新:具有较少类似代码的新代码,这是基于适配器设计模式的思想:

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

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;

}
我希望

我能回复您的问题作为评论,但我没有足够的声誉来这样做。

如果向量是排序的,那么使用"std::binary_search"可能是可用于搜索向量的最快算法,但请记住,必须对向量进行排序。

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

"binary_search"可能对您有用,也可能不起作用,因为您告诉我们假设您不能更改任何一个类;如果是这种情况,如果需要此类操作,您将无法实现"小于"运算符的正确重载。

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

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

在某些时候,您必须区分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
}