如何确定std :: vector中是否存在某个项?

Joa*_*nge 587 c++ vector std

我想做的就是检查一个元素是否存在于向量中,所以我可以处理每个案例.

if ( item_present )
   do_this();
else
   do_that();
Run Code Online (Sandbox Code Playgroud)

MSN*_*MSN 873

您可以使用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()
Run Code Online (Sandbox Code Playgroud)

这将返回一个bool(true如果存在,false否则).用你的例子:

#include <algorithm>
#include <vector>

if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
   do_this();
else
   do_that();
Run Code Online (Sandbox Code Playgroud)

  • 我没有看到count()如何比find()更快,因为一旦找到一个元素,find()就会停止,而count()总是要扫描整个序列. (214认同)
  • 不要忘记`#include <algorithm>`否则你可能会得到非常奇怪的错误,例如'找不到命名空间std中的匹配函数' (113认同)
  • 尽管STL是"面向对象的",但是它仍然没有困扰任何人,`.find()`仍然不是`std :: vector`的成员函数,正如你所期望的那样?我想知道这是否是模板的结果. (76认同)
  • @bobobobo:OOP与成员与非成员无关.并且有一种广泛的思想流派,如果某些东西不必是成员,或者当它作为成员实施时没有给予任何好处,那么它不应该是成员; `std :: vector <> :: find()`不会给任何优势,也不需要它,因此,不,它不应该是成员.另见http://en.wikipedia.org/wiki/Coupling_%28computer_programming%29 (70认同)
  • @phresnel我认为"当它作为成员实现时没有任何优势"对于这种情况是错误的.优点是简化和清晰的界面.例如:`mvec.find(key)!= mvec.cend()`比`std :: find(mvec.cbegin(),mvec.cend(),key)更好!= mvec.cend()`. (33认同)
  • 有可能.这取决于您搜索空向量的频率. (9认同)
  • @bobobobo:find()函数不是向量成员的原因是它效率低下.当STL的一个对象有一个成员时,这意味着它是一种有用的,有效的方法; 它表明你应该使用它.由于find()无法有效地为向量实现,因此它不是向量的成员,并且建议如果需要使用find()操作,则使用不同的容器.它与其他评论中提到的STL"设计糟糕"无关. (5认同)
  • @ArtOfWarfare第三,您可能会发现`end()调用是由编译器内联的,因此根本没有实际的`call`而只是一个原始指针. (4认同)
  • @ArtOfWarfare由于缓存局部性而排序的`vector`通常比`map`或`set`快得多. (3认同)
  • @Cludiu 在 C++ 中,你可以使用任何你喜欢的语法,只需要一页最丑的代码和 [voilà](http://ideone.com/QlCCl7) (3认同)
  • @ ap31:这是真的,但当我在制作中使用这样的代码时,人们会对我大喊:( (3认同)
  • 这太糟糕了。应该有一个 std::vector::contains 方法。 (3认同)
  • GCC/GXX 在使用 `std::find` 时忘记 `#include` `&lt;algorithm&gt;` 标头的错误消息甚至变得更糟:`error: cannot bind non-const lvalue reference of type '__gnu_cxx:: __normal_iterator&lt;const int*, std::vector&lt;int&gt; &gt;&amp;' 到 '__gnu_cxx::__normal_iterator&lt;const int*, std::vector&lt;int&gt; &gt;' 类型的右值 (2认同)
  • @bobobobo 各地有如此多不同的编程范例,这对新手来说很困难。 (2认同)
  • 很公平。然而,讨论的是隐式搜索整个范围的假设过载,因此不需要范围细节。如果并且每当人们希望在一个范围(不是整个范围)上搜索时,您可以使用 find 或像您提到的那样的成员函数。 (2认同)
  • @SebastianMach我明白,`std::vector::find()`没有实现,因为它并不比`std::find()`更好。问题是,程序员将某个数据结构从“std::vector”升级到“std::multiset”(或“std::set”),然后必须遍历代码并更新每个地方,其中执行“find()”。如果 `std::(multi)set` 和 `std::vector` 的 API 尽可能相似,那就太好了。 (2认同)

Bri*_*eal 109

正如其他人所说,使用STL findfind_if函数.但是,如果你在非常大的矢量搜索,这会影响性能,您可能要排序的载体,然后使用binary_search,lower_boundupper_bound算法.

  • 排序是O(nlogn),所以只有当你做的不仅仅是O(logn)搜索时,它才有价值. (27认同)
  • @liori 是的,这取决于您的使用模式。如果你只需要排序一次,那么重复多次搜索它可以节省你。 (7认同)
  • 好答案!查找总是o(n).如果与随机访问迭代器一起使用,lower_bound是o(log(n)). (3认同)

m-s*_*arp 46

使用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;
}
Run Code Online (Sandbox Code Playgroud)

  • 根据OP的需要,find_if()也可能是合适的.它允许使用任意谓词而不是相等进行搜索. (2认同)

Bin*_*eng 38

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

if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
      // Found the item
}
Run Code Online (Sandbox Code Playgroud)

如果您的矢量是有序的,请使用binary_search方法Brian Neal建议:

if(binary_search(vector.begin(), vector.end(), item)){
     // Found the item
}
Run Code Online (Sandbox Code Playgroud)

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

  • 你不是指'std :: sort`吗?`qsort`对矢量效率非常低......参见:http://stackoverflow.com/questions/12308243/trying-to-use-qsort-with-vector (3认同)

And*_*wel 21

我用这样的东西......

#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
Run Code Online (Sandbox Code Playgroud)

......就这样,它实际上清晰可读.(显然你可以在多个地方重用模板).

  • 你基本上是在写:“if true return true else return false”。该方法可以是一行:`return std::find(Vec.begin(), Vec.end(), Element) != Vec.end();` (3认同)

Pav*_*aka 13

从 C++20 开始,使用范围 ( #include <ranges>)

    //SAMPLE DATA
    std::vector<int> vecOfElements = { 2,4,6,8 };

    //DO SOMETHING IF 8 IN VECTOR
    if (std::ranges::find(vecOfElements, 8) != vecOfElements.end())
    {
        std::cout << "DO SOMETHING" << std::endl;
    }
Run Code Online (Sandbox Code Playgroud)


Deq*_*ing 11

在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();
Run Code Online (Sandbox Code Playgroud)

  • 当我们有 std::find() 时,为什么要使用 std::any_of() 呢? (4认同)
  • `bind1st` 和 `bind2nd` [自 C++11 起已弃用](https://en.cppreference.com/w/cpp/utility/functional/bind12) 并在 C++17 中完全删除。将 `bind` 与 `placeholders` 和/或 lambdas 一起使用。 (2认同)
  • 如果目的只是检查成员资格,那么当我们有“std::any_of”时为什么要使用“std::find()”呢? (2认同)

Mar*_*rst 11

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

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();
}
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,这有时过于宽泛 - 例如,它适用于std :: set,但与find()成员函数相比,性能可怕.我发现最好为搜索速度更快的容器添加专门化(set/map,unordered_*) (4认同)

Dav*_*ley 10

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

std :: vector是选择的容器,除非你有另一个的理由,并且按值查找可能是这样的原因.


Mik*_*ail 9

在 C++23 中,我们终于有了最明显的解决方案

if (std::ranges::contains(vec, item))
   do_this();
else
   do_that();
Run Code Online (Sandbox Code Playgroud)


Fra*_*ank 8

使用STL 查找功能.

请记住,还有一个find_if函数,如果您的搜索更复杂,可以使用它,例如,如果您不只是查找元素,但是,例如,想要查看是否存在满足某个元素的元素condition,例如,以"abc"开头的字符串.(find_if会给你一个指向第一个这样的元素的迭代器).


Mik*_*ail 7

使用boost可以使用any_of_equal:

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

bool item_present = boost::algorithm::any_of_equal(vector, element);
Run Code Online (Sandbox Code Playgroud)


小智 5

你可以试试这段代码:

#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()
}
Run Code Online (Sandbox Code Playgroud)


Tan*_*ash 5

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

std::find(vector.begin(), vector.end(), item) != vector.end()
Run Code Online (Sandbox Code Playgroud)

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