我要做的就是检查向量中是否存在元素,以便我处理每种情况。

if ( item_present )
   do_this();
else
   do_that();


评论

搜索向量非常慢,因为您必须查看向量的每个元素,因此如果您要进行大量查找,请考虑使用地图

@naumcho:如果对向量进行排序,则始终会进行二进制搜索,如下所示。这使它与映射一样快,如果只存储值(不存储键/值映射),那么它将使用更少的内存。

映射当然不是最佳选择,但使用set可能会有用。如果需要O(1)查找时间,则可以使用hash_set。

一个重复的问题上存在一个极好的答案:stackoverflow.com/a/3451045/472647

如果要多次搜索不同的数字,则哈希表会更有效。

#1 楼

您可以使用std::find中的<algorithm>

#include <vector>
vector<int> vec; 
//can have other data types instead of int but must same datatype as item 
std::find(vec.begin(), vec.end(), item) != vec.end()


这将返回布尔值(如果存在true,否则返回false)。以您的示例为例:

#include <algorithm>
#include <vector>

if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
   do_this();
else
   do_that();


评论


我不知道count()会比find()快多少,因为find()一旦找到一个元素就停止,而count()总是必须扫描整个序列。

–Éric Malenfant
09年2月21日,在3:29

不要忘记#include ,否则您可能会遇到非常奇怪的错误,例如“在命名空间std中找不到匹配的函数”

–rustyx
2012年2月2日15:46

尽管STL是“面向对象的”,.find()仍然不是std :: vector的成员函数,正如您期望的那样,这是否使任何人感到困扰?我想知道这是否是模板的结果。

– bobobobo
2012年12月7日在2:33



@bobobobo:OOP与成员与非成员无关。并且有一种广泛的思想流派,即如果某件事不必成为成员,或者当它作为成员实施时没有带来任何好处,那么它就不应成为成员。 std :: vector <> :: find()不会带来任何好处,也不是必需的,因此,不,它不应该是成员。另请参见en.wikipedia.org/wiki/Coupling_%28computer_programming%29

–塞巴斯蒂安·马赫
13年2月4日在13:54



@phresnel我会争辩说,“当作为成员实施时,它没有任何优势时”对于这种情况是错误的。优点是简化和更清晰的界面。例如:mvec.find(key)!= mvec.cend()比std :: find(mvec.cbegin(),mvec.cend(),key)!= mvec.cend()更可取。

–口语
2015年4月29日在20:09

#2 楼

正如其他人所说,请使用STL findfind_if函数。但是,如果要搜索非常大的向量,这会影响性能,则可能需要对向量进行排序,然后使用binary_searchlower_boundupper_bound算法。

评论


好答案!查找始终为o(n)。如果与随机访问迭代器一起使用,lower_bound为o(log(n))。

–斯蒂芬·埃德蒙兹(Stephen Edmonds)
09年7月8日在19:54

不过排序是O(nlogn),因此仅当您进行的搜索超过O(logn)搜索时才值得。

– liori
2014年6月15日下午0:48

@liori是的,这取决于您的使用模式。如果您只需要对它排序一次,那么反复进行多次搜索可以节省您的时间。

–布赖恩·尼尔(Brian Neal)
2014年6月17日下午16:24

@Brian Neal,如果必须对很多向量进行搜索,则对大向量进行排序是值得的。如果只需要查找一次元素,则排序将为O(nlogn),O(n)会更好:)

– swapnil B.
18年3月11日在18:17

请注意,这可能会对分支预测造成破坏。

– Brice M. Dempsey
8月18日12:23

#3 楼

使用stl的算法标头中的find。我已经说明了int类型的用法。您可以使用任何喜欢的类型,只要您可以比较相等性即可(如果需要为自定义类添加超载==)。

#include <algorithm>
#include <vector>

using namespace std;
int main()
{   
    typedef vector<int> IntContainer;
    typedef IntContainer::iterator IntIterator;

    IntContainer vw;

    //...

    // find 5
    IntIterator i = find(vw.begin(), vw.end(), 5);

    if (i != vw.end()) {
        // found it
    } else {
        // doesn't exist
    }

    return 0;
}


评论


根据OP的需求,find_if()也可能合适。它允许使用任意谓词而不是等于进行搜索。

–Éric Malenfant
09年2月20日在22:12

糟糕,看到您的评论为时已晚。我给出的答案也提到了find_if。

–坦白
09年2月20日在22:19

#4 楼

如果没有订购矢量,请使用MSN建议的方法:

if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
      // Found the item
}


如果订购矢量,请使用binary_search方法Brian Neal建议:

if(binary_search(vector.begin(), vector.end(), item)){
     // Found the item
}

二进制搜索产生O(log n)最坏情况的性能,这比第一种方法更有效。为了使用二进制搜索,您可以使用qsort首先对向量进行排序以确保其有序。

评论


您不是说std​​ :: sort吗? qsort在向量上效率很低。...请参阅:stackoverflow.com/questions/12308243/…

–詹森·米克(Jason R. Mick)
13年8月16日在1:57

对于较大的容器,二进制搜索的性能更好,但是对于较小的容器,简单的线性搜索可能会更快或更快速。

–BillT
17年3月31日14:07在

#5 楼

我使用这样的东西...

#include <algorithm>


template <typename T> 
const bool Contains( std::vector<T>& Vec, const T& Element ) 
{
    if (std::find(Vec.begin(), Vec.end(), Element) != Vec.end())
        return true;

    return false;
}

if (Contains(vector,item))
   blah
else
   blah


...那样,它实际上是清晰易读的。
(显然,您可以在多个地方重复使用模板)。

评论


您可以使用2个类型名称使其适用于列表或向量

– Erik Aronesty
15年3月3日在15:36

如果您使用容器中的value_type作为元素类型,则@ErikAronesty可以避免使用1个模板参数。我添加了这样的答案。

–马丁·布罗德赫斯特(Martin Broadhurst)
16年2月11日在21:40

您基本上是在写:如果为true,则返回true,否则返回false。该方法可以是以下一行:return std :: find(Vec.begin(),Vec.end(),Element)!= Vec.end();

–查尔斯·格纳(Charles Gueunet)
10月8日7:52

#6 楼

在C ++ 11中,您可以使用any_of。例如,如果它是vector<string> v;,则:

if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
   do_this();
else
   do_that();


或者使用lambda:

if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
   do_this();
else
   do_that();


评论


从C ++ 11开始不推荐使用bind1st和bind2nd,并在C ++ 17中将其完全删除。请改用占位符和/或lambda绑定。

– andreee
19年4月30日在7:50

#7 楼

这是一个适用于任何容器的函数:

template <class Container> 
const bool contains(const Container& container, const typename Container::value_type& element) 
{
    return std::find(container.begin(), container.end(), element) != container.end();
}


请注意,您可以使用1个模板参数,因为您可以从Container中提取value_type。您需要typename,因为Container::value_type是从属名称。

评论


请注意,有时这有点太宽泛-例如,它可用于std :: set,但与find()成员函数相比,性能却很差。我发现最好为搜索速度更快的容器(设置/地图,unordered_ *)添加一个专门化的容器

–安迪·克鲁维尔(Andy Krouwel)
16年2月2日,12:01

也许有一天,他们最终会将其添加到stdlib中,而不是人们不得不一遍又一遍地问如何重新发明这么小的轮子。现在在C ++ 20中有范围是完全可行的,因此可以将其称为范围而不是容器,而鲍勃是您的叔叔。

– underscore_d
7月1日在16:06

#8 楼

请记住,如果您要进行大量查找,则可以使用STL容器来更好地进行查找。我不知道您的应用程序是什么,但是像std :: map这样的关联容器可能值得考虑。

std :: vector是首选的容器,除非您有其他理由并进行查找按值计算可能就是这样的原因。

评论


即使对向量进行值查询,只要对向量进行排序并且您使用binary_search,lower_bound或upper_bound,它也是一个不错的选择。如果容器的内容在两次查找之间更改,则vector不太好,因为需要再次排序。

– Renze de Waal
09年2月20日在22:49

#9 楼

请使用STL find函数。

请记住,还有一个find_if函数,如果您的搜索更为复杂,即您不只是在寻找元素,而是可以使用它,例如,想要查看是否存在满足特定条件的元素,例如,以“ abc”开头的字符串。 (find_if将为您提供一个指向第一个此类元素的迭代器)。

#10 楼

使用boost可以使用any_of_equal

#include <boost/algorithm/cxx11/any_of.hpp>

bool item_present = boost::algorithm::any_of_equal(vector, element);


#11 楼

您可以尝试以下代码:

#include <algorithm>
#include <vector>

// You can use class, struct or primitive data type for Item
struct Item {
    //Some fields
};
typedef std::vector<Item> ItemVector;
typedef ItemVector::iterator ItemIterator;
//...
ItemVector vtItem;
//... (init data for vtItem)
Item itemToFind;
//...

ItemIterator itemItr;
itemItr = std::find(vtItem.begin(), vtItem.end(), itemToFind);
if (itemItr != vtItem.end()) {
    // Item found
    // doThis()
}
else {
    // Item not found
    // doThat()
}


#12 楼

您可以使用find名称空间中的std函数,即std::find。您可以从要搜索的向量中传递std::findbegin迭代器的end函数,以及要查找的元素,并将生成的迭代器与向量的末尾进行比较,以查看它们是否匹配。

std::find(vector.begin(), vector.end(), item) != vector.end()


您还可以取消引用该迭代器,并像其他任何迭代器一样正常使用它。

#13 楼

您也可以使用count。
它将返回向量中存在的项目数。

int t=count(vec.begin(),vec.end(),item);


评论


find比count快,因为它在第一场比赛后就不会继续计数。

– Camille Goudeseune
15年8月16日在20:27

#14 楼

如果要在向量中找到字符串:

    struct isEqual
{
    isEqual(const std::string& s): m_s(s)
    {}

    bool operator()(OIDV* l)
    {
        return l->oid == m_s;
    }

    std::string m_s;
};
struct OIDV
{
    string oid;
//else
};
VecOidv::iterator itFind=find_if(vecOidv.begin(),vecOidv.end(),isEqual(szTmp));


#15 楼

(C ++ 17和更高版本):

还可以使用std::search

这对于搜索元素序列也很有用。

#include <algorithm>
#include <iostream>
#include <vector>

template <typename Container>
bool search_vector(const Container& vec, const Container& searchvec)
{
    return std::search(vec.begin(), vec.end(), searchvec.begin(), searchvec.end()) != vec.end();
}

int main()
{
     std::vector<int> v = {2,4,6,8};

     //THIS WORKS. SEARCHING ONLY ONE ELEMENT.
     std::vector<int> searchVector1 = {2};
     if(search_vector(v,searchVector1))
         std::cout<<"searchVector1 found"<<std::endl;
     else
         std::cout<<"searchVector1 not found"<<std::endl;

     //THIS WORKS, AS THE ELEMENTS ARE SEQUENTIAL.
     std::vector<int> searchVector2 = {6,8};
     if(search_vector(v,searchVector2))
         std::cout<<"searchVector2 found"<<std::endl;
     else
         std::cout<<"searchVector2 not found"<<std::endl;

     //THIS WILL NOT WORK, AS THE ELEMENTS ARE NOT SEQUENTIAL.
     std::vector<int> searchVector3 = {8,6};
     if(search_vector(v,searchVector3))
         std::cout<<"searchVector3 found"<<std::endl;
     else
         std::cout<<"searchVector3 not found"<<std::endl;
}


还可以灵活地传递一些搜索算法。请参阅此处。

https://en.cppreference.com/w/cpp/algorithm/search

#16 楼

template <typename T> bool IsInVector(const T & what, const std::vector<T> & vec)
{
    return std::find(vec.begin(),vec.end(),what)!=vec.end();
}


评论


为什么要使用指针并冒用户传递您不处理的nullptr的风险?根本没有必要。另外,您复制T what,这可能会很昂贵并且是不必要的工作。这两个参数都应该是const引用,而不是当前引用。最后,我不知道为什么人们曾经写过(条件)是否返回true;否则返回假;他们什么时候才可以写退货条件;

– underscore_d
7月1日在16:09



感谢您的建议,我当时并没有那么多经验,同时又改用了Java :)我更新了注释,让我知道它是否更好,或者是否还有需要修复的地方。

–user3157855
7月2日17:56



现在您收到引用而不是指针,您需要使用。而不是->。

– underscore_d
7月3日7:57

#17 楼

我个人最近使用模板来一次处理多种类型的容器,而不仅仅是处理向量。我在网上找到了一个类似的示例(不记得在哪里),因此,无论我从谁那里窃取资金,都应归功于它。这种特殊的模式似乎也可以处理原始数组。

template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
bool contains(Container && c, T v)
{
    return std::find(std::begin(c), std::end(c), v) != std::end(c);
}


#18 楼

使用牛顿C ++比使用std :: find更容易,具有自文档说明和更加快捷,因为它直接返回布尔值。

bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )

bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )


我认为函数的作用很明显。

include <newton/algorithm/algorithm.hpp>

if ( newton::exists_linear(first, last, value) )
   do_this();
else
   do_that();