std :: vector에 항목이 있는지 확인하는 방법?


616

내가하고 싶은 것은 요소가 벡터에 존재하는지 여부를 확인하는 것이므로 각 경우를 처리 할 수 ​​있습니다.

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

2
벡터의 모든 단일 요소를 살펴 봐야하므로 벡터 검색은 매우 느립니다. 많은 조회를 수행하는 경우 맵 사용을 고려하십시오.
naumcho

7
@ naumcho : 벡터가 정렬되면 아래에 게시 된 것처럼 항상 이진 검색이 있습니다. 이것은 맵만큼 빠르며 키 / 값 맵이 아닌 값만 저장하는 경우 훨씬 적은 메모리를 사용하게됩니다.
Adam Hawes

4
지도가 최선의 선택은 아니지만 set을 사용하는 것이 유용 할 수 있습니다. O (1) 조회 시간이 필요한 경우 hash_set을 사용하십시오.
Philipp

중복 질문에 대한 훌륭한 답변 : stackoverflow.com/a/3451045/472647
CodeMouse92

1
다른 숫자를 여러 번 검색하려는 경우 해시 테이블이 더 효율적입니다.
NL628

답변:


915

다음 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();

216
count ()가 항상 전체 시퀀스를 스캔 해야하는 동안 find ()는 하나의 요소를 찾 자마자 멈추기 때문에 count ()가 find ()보다 더 빠를 수있는 방법을 알지 못합니다.
Éric Malenfant

114
잊지 마세요. #include <algorithm>'네임 스페이스 std에서 일치하는 함수를 찾을 수 없습니다'와 같은 매우 이상한 오류가 발생할 수 있습니다.
rustyx

80
그것은되는 STL에도 불구하고 "객체 지향"는 것을 누군가를 성가 시게하지 않은 .find()아직 하지 의 멤버 함수 std::vector당신이해야합니다 예상대로? 이것이 어떻게 든 템플릿 화의 결과인지 궁금합니다.
bobobobo

71
@bobobobo : OOP는 멤버와 비 멤버와 아무 관련이 없습니다. 그리고 무언가가 회원이 될 필요가 없거나 회원으로서 구현 될 때 어떤 이점도 제공하지 않을 경우 회원이되어서는 안된다는 생각이 널리 퍼져 있습니다. std::vector<>::find()어떤 이점도 제공하지 않으며 필요하지도 않습니다. 따라서 회원이 아니어야합니다. 참조 en.wikipedia.org/wiki/Coupling_%28computer_programming%29
세바스찬 마하

36
@phresnel 나는이 경우 "멤버로서 구현 될 때 어떤 이점도 제공하지 않을 때"는 거짓이라고 주장 할 것이다. 장점은 간단하고 명확한 인터페이스입니다. 예를 들면 다음 mvec.find(key) != mvec.cend()것이 바람직하다 std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend().
swalog

113

다른 사람들이 말했듯이 STL find또는 find_if기능을 사용하십시오 . 매우 큰 벡터에서 검색이 성능에 영향을하는 경우에, 당신은 당신의 벡터를 정렬 할 후 사용할 수 있습니다 binary_search, lower_bound또는 upper_bound알고리즘을.


3
좋은 대답입니다! 찾기는 항상 o (n)입니다. 랜덤 액세스 반복자와 함께 사용되는 경우 lower_bound는 o (log (n))입니다.
Stephen Edmonds

30
정렬은 O (nlogn)이므로 O (logn) 이상의 검색을 수행하는 경우에만 가치가 있습니다.
liori

7
@liori 사실 사용 패턴에 따라 다릅니다. 한 번만 정렬 해야하는 경우 반복적으로 많은 검색을 수행하면 저장 할 수 있습니다.
Brian Neal

1
@Brian Neal, 큰 벡터를 정렬하는 것은 많은 요소 검색이 필요한 경우 가치가 있습니다. 정렬은 O (nlogn)이되고 O (n)은 요소를 한 번만 찾아야하는 경우에 더 좋습니다 :)
Swapnil B.

47

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

2
OP의 요구에 따라 find_if ()도 적합 할 수 있습니다. 평등 대신 임의의 술어를 사용하여 검색 할 수 있습니다.
Éric Malenfant

죄송합니다. 댓글이 너무 늦었습니다. 내가 준 대답은 find_if도 언급합니다.
Frank

39

벡터를 주문하지 않은 경우 MSN이 제안한 방법을 사용하십시오.

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

벡터가 주문 된 경우 Brian Neal이 제안한 binary_search 메소드를 사용하십시오.

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

이진 검색은 O (log n) 최악의 성능을 제공하며 이는 첫 번째 방법보다 훨씬 효율적입니다. 이진 검색을 사용하려면 qsort를 사용하여 벡터가 정렬되도록 벡터를 먼저 정렬 할 수 있습니다.


3
당신은 의미하지 std::sort않습니까? qsort벡터에 매우 비효율적입니다 .... 참조 : stackoverflow.com/questions/12308243/…
Jason R. Mick

1
이진 검색은 더 큰 컨테이너에서는 더 잘 수행되지만 작은 컨테이너에서는 단순 선형 검색이 빠르거나 빠를 수 있습니다.
BillT

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

... 그런 식으로 실제로 명확하고 읽을 수 있습니다. (여러분은 여러 곳에서 템플릿을 재사용 할 수 있습니다).


그리고 당신은 2 개의 타입 이름을 사용하여리스트 나 벡터를 위해 그것을 작동시킬 수 있습니다
Erik Aronesty

@ErikAronesty 당신은 value_type요소 유형에 대해 컨테이너에서 사용하면 1 개의 템플릿 인수로 벗어날 수 있습니다 . 나는 이와 같은 답변을 추가했습니다.
마틴 브로드 허스트

13

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();

또는 람다를 사용하십시오.

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

1
bind1st하고 bind2nd있다 (11) ++ C부터 사용되지 않습니다 완전히 17 ++ C에서 제거. 사용 bind으로 placeholders대신 및 / 또는 람다.
andreee

11

모든 컨테이너에서 작동하는 함수는 다음과 같습니다.

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();
}

value_type컨테이너에서를 추출 할 수 있기 때문에 1 개의 템플릿 매개 변수를 사용하여 벗어날 수 있습니다 . 당신은 필요 typename하기 때문에이 Container::value_typeA는 따라 이름 .


5
예를 들어 std :: set에서는 작동하지만 find () 멤버 함수와 비교할 때 끔찍한 성능을 제공합니다. 검색 속도가 빠른 컨테이너에 대한 전문화를 추가하는 것이 가장 좋습니다 (set / map, unorder_ *)
Andy Krouwel

10

많은 조회를 수행하려는 경우 더 나은 STL 컨테이너가 있음을 명심하십시오. 귀하의 응용 프로그램이 무엇인지 모르지만 std :: map과 같은 연관 컨테이너를 고려해 볼 가치가 있습니다.

std :: vector는 다른 이유가없는 한 선택한 컨테이너이며 값별 조회가 그러한 이유 일 수 있습니다.


값별로 조회하는 경우에도 벡터가 정렬되고 binary_search, lower_bound 또는 upper_bound를 사용하는 한 벡터를 선택하는 것이 좋습니다. 컨테이너의 내용이 조회간에 변경되면 다시 정렬해야하므로 벡터가 그리 좋지 않습니다.
Renze de Waal

8

STL 찾기 기능을 사용하십시오 .

find_if 함수 도 있습니다. 검색이 더 복잡한 경우, 즉 요소를 찾는 것이 아니라 특정 요소를 충족시키는 요소가 있는지 확인하려는 경우 사용할 수 있습니다. 조건 (예 : "abc"로 시작하는 문자열) ( find_if첫 번째 요소를 가리키는 반복자를 제공합니다).


7

부스트를 사용하면 다음을 사용할 수 있습니다 any_of_equal.

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

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

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()
}

3

네임 스페이스 find에 있는 함수 를 사용할 수 있습니다 ( std예 :) std::find. 찾고자하는 요소와 함께 std::find함수 beginend반복자를 전달하고 결과 반복자를 벡터의 끝과 비교하여 일치하는지 여부를 확인합니다.

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

또한 이터레이터를 역 참조하여 다른 이터레이터와 마찬가지로 정상적으로 사용할 수 있습니다.


3

count도 사용할 수 있습니다. 벡터에있는 항목 수를 반환합니다.

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

11
findcount첫 번째 경기 후에 계산을 계속하지 않기 때문에 보다 빠릅니다 .
Camille Goudeseune

2

벡터에서 문자열을 찾으려면 다음을 수행하십시오.

    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));

2

C ++ 연산자를 사용하는 다른 샘플.

#include <vector>
#include <algorithm>
#include <stdexcept>

template<typename T>
inline static bool operator ==(const std::vector<T>& v, const T& elem)
{
  return (std::find(v.begin(), v.end(), elem) != v.end());
}

template<typename T>
inline static bool operator !=(const std::vector<T>& v, const T& elem)
{
  return (std::find(v.begin(), v.end(), elem) == v.end());
}

enum CODEC_ID {
  CODEC_ID_AAC,
  CODEC_ID_AC3,
  CODEC_ID_H262,
  CODEC_ID_H263,
  CODEC_ID_H264,
  CODEC_ID_H265,
  CODEC_ID_MAX
};

void main()
{
  CODEC_ID codec = CODEC_ID_H264;
  std::vector<CODEC_ID> codec_list;

  codec_list.reserve(CODEC_ID_MAX);
  codec_list.push_back(CODEC_ID_AAC);
  codec_list.push_back(CODEC_ID_AC3);
  codec_list.push_back(CODEC_ID_H262);
  codec_list.push_back(CODEC_ID_H263);
  codec_list.push_back(CODEC_ID_H264);
  codec_list.push_back(CODEC_ID_H265);

  if (codec_list != codec)
  {
    throw std::runtime_error("codec not found!");
  }

  if (codec_list == codec)
  {
    throw std::logic_error("codec has been found!");
  }
}

4
그런 식으로 연산자 오버로드를 사용하지 않는 것이 좋습니다.
레온

2
레온, 나는 당신의 의견에 동의합니다. 단위 테스트를보다 명확하게하기 위해 사용합니다.
Valdemar_Rudolfovich

1
template <typename T> bool IsInVector(T what, std::vector<T> * vec)
{
    if(std::find(vec->begin(),vec->end(),what)!=vec->end())
        return true;
    return false;
}

1

(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


1

나는 벡터 만 다루지 않고 여러 유형의 컨테이너를 한 번에 처리하기 위해 개인적으로 늦은 템플릿을 사용했습니다. 나는 온라인에서 비슷한 예를 찾았습니다 (어디를 기억하지 못합니까). 크레딧은 내가 이것을 인용 한 사람에게갑니다. 이 특정 패턴은 원시 배열도 처리하는 것으로 보입니다.

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

-4

Newton C ++를 사용하면 직접 bool을 반환하기 때문에 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();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.