Как найти позицию элемента в std::vector?
Мне нужно найти позицию элемента в std::vector, чтобы использовать ее для ссылки на элемент в другом векторе:
int find( const vector<type>& where, int searchParameter )
{
for( int i = 0; i < where.size(); i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return -1;
}
// caller:
const int position = find( firstVector, parameter );
if( position != -1 ) {
doAction( secondVector[position] );
}
однако vector::size()
возвращает size_t
, что соответствует интегральному типу unsigned
, который не может непосредственно хранить -1
. Как я могу сигнализировать, что элемент не найден в векторе при использовании size_t
вместо int
в качестве индекса?
Ответы
Ответ 1
Вы можете использовать std::numeric_limits<size_t>::max()
для элементов, которые не были найдены. Это допустимое значение, но создать контейнер с таким максимальным индексом невозможно. Если std::vector
имеет размер, равный std::numeric_limits<size_t>::max()
, то максимально допустимый индекс будет (std::numeric_limits<size_t>::max()-1)
, так как элементы подсчитываются от 0.
Ответ 2
Взгляните на ответы на этот вопрос: Недопустимое значение для size_t?. Также вы можете использовать std:: find_if с std:: distance, чтобы получить индекс.
std::vector<type>::iterator iter = std::find_if(vec.begin(), vec.end(), comparisonFunc);
size_t index = std::distance(vec.begin(), iter);
if(index == vec.size())
{
//invalid
}
Ответ 3
Прежде всего, вам действительно нужно хранить такие индексы? Вы заглянули в std:: map, позволяя вам хранить пары ключ = > значение?
Во-вторых, если вы использовали итераторы вместо этого, вы могли бы вернуть std::vector.end(), чтобы указать неверный результат. Чтобы преобразовать итератор в индекс, вы просто используете
size_t i = it - myvector.begin();
Ответ 4
std::vector
имеет итераторы с произвольным доступом. Вы можете сделать с ними арифметику указателей. В частности, это my_vec.begin() + my_vec.size() == my_vec.end()
всегда выполняется. Таким образом, вы могли бы сделать
const vector<type>::const_iterator pos = std::find_if( firstVector.begin()
, firstVector.end()
, some_predicate(parameter) );
if( position != firstVector.end() ) {
const vector<type>::size_type idx = pos-firstVector.begin();
doAction( secondVector[idx] );
}
В качестве альтернативы всегда std::numeric_limits<vector<type>::size_type>::max()
используется как недопустимое значение.
Ответ 5
В этом случае безопасно отбрасывать неподписанную часть, если ваш вектор не может получить ДЕЙСТВИТЕЛЬНО большой.
Я бы вытащил where.size() в локальную переменную, поскольку она не будет меняться во время вызова. Что-то вроде этого:
int find( const vector<type>& where, int searchParameter ){
int size = static_cast<int>(where.size());
for( int i = 0; i < size; i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return -1;
}
Ответ 6
Что-то вроде этого, я думаю. find_if_counted.hpp
:
#ifndef FIND_IF_COUNTED_HPP
#define FIND_IF_COUNTED_HPP
#include <algorithm>
namespace find_if_counted_impl
{
template <typename Func>
struct func_counter
{
explicit func_counter(Func& func, unsigned &count) :
_func(func),
_count(count)
{
}
template <typename T>
bool operator()(const T& t)
{
++_count;
return _func(t);
}
private:
Func& _func;
unsigned& _count;
};
}
// generic find_if_counted,
// returns the index of the found element, otherwise returns find_if_not_found
const size_t find_if_not_found = static_cast<size_t>(-1);
template <typename InputIterator, typename Func>
size_t find_if_counted(InputIterator start, InputIterator finish, Func func)
{
unsigned count = 0;
find_if_counted_impl::func_counter<Func> f(func, count);
InputIterator result = find_if(start, finish, f);
if (result == finish)
{
return find_if_not_found;
}
else
{
return count - 1;
}
}
#endif
Пример:
#include "find_if_counted.hpp"
#include <cstdlib>
#include <iostream>
#include <vector>
typedef std::vector<int> container;
int rand_number(void)
{
return rand() % 20;
}
bool is_even(int i)
{
return i % 2 == 0;
}
int main(void)
{
container vec1(10);
container vec2(10);
std::generate(vec1.begin(), vec1.end(), rand_number);
std::generate(vec2.begin(), vec2.end(), rand_number);
unsigned index = find_if_counted(vec1.begin(), vec1.end(), is_even);
if (index == find_if_not_found)
{
std::cout << "vec1 has no even numbers." << std::endl;
}
else
{
std::cout << "vec1 had an even number at index: " << index <<
" vec2 corresponding number is: " << vec2[index] << std::endl;
}
}
Хотя я чувствую, что делаю что-то глупое...: X Любые исправления приветствуются, конечно.
Ответ 7
Если вектор имеет N элементов, для поиска есть N + 1 возможных ответов. std:: find и std:: find_if возвращают итератор найденному элементу OR end(), если элемент не найден. Чтобы изменить код как можно меньше, функция поиска должна вернуть эквивалентную позицию:
size_t find( const vector<type>& where, int searchParameter )
{
for( size_t i = 0; i < where.size(); i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return where.size();
}
// caller:
const int position = find( firstVector, parameter );
if( position != secondVector.size() ) {
doAction( secondVector[position] );
}
Я все равно использовал бы std:: find_if.
Ответ 8
Вы, вероятно, не должны использовать свою собственную функцию здесь.
Используйте find() из STL.
Пример:
list L;
L.push_back(3);
L.push_back(1);
L.push_back(7);
list::iterator result = find(L.begin(), L.end(), 7);
assert(result == L.end() || *result == 7);
Ответ 9
Возьмите вектор целого и ключа (который мы найдем в векторе).... Теперь мы перемещаем вектор до тех пор, пока не найдем значение ключа или последний индекс (иначе)..... Если мы найдем ключ, тогда напечатаем в противном случае напечатайте "-1".
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>str;
int flag,temp key, ,len,num;
flag=0;
cin>>len;
for(int i=1; i<=len; i++)
{
cin>>key;
v.push_back(key);
}
cin>>num;
for(int i=1; i<=len; i++)
{
if(str[i]==num)
{
flag++;
temp=i-1;
break;
}
}
if(flag!=0) cout<<temp<<endl;
else cout<<"-1"<<endl;
str.clear();
return 0;
}