2009-09-15 15 views
32

Tengo que encontrar una posición de elemento en un std :: vector para utilizarlo para hacer referencia a un elemento en otro vectorial:¿Cómo encuentro una posición de elemento en 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]); 
} 

embargo vector::size() vuelve size_t lo que corresponde a un tipo entero unsigned que no pueden directamente tienda -1. ¿Cómo señalo que el elemento no se encuentra en un vector cuando se utiliza size_t en lugar de int como índice?

+8

Creo que el título de la pregunta debe ser cambiado. El problema no es cómo encontrar la posición del elemento, se trata de hacer referencia a los elementos en dos vectores. –

+0

Bueno, si el problema es aproximadamente -1, eche un vistazo [aquí] (http://www.cplusplus.com/reference/climits/), o puede usar 'return (size_t) -1;' – ST3

Respuesta

14

Puede usar std::numeric_limits<size_t>::max() para los elementos que no se encontraron. Es un valor válido, pero es imposible crear un contenedor con dicho índice máximo. Si std::vector tiene tamaño igual a std::numeric_limits<size_t>::max(), a continuación, el índice máximo permitido será (std::numeric_limits<size_t>::max()-1), ya que los elementos contados a partir de 0.

56

Eche un vistazo a las respuestas a esta pregunta: Invalid value for size_t?. También puede usar std :: find_if con std :: distance para obtener el índice.

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

O podría verificar el iterador contra 'where.end()', y calcule/use la distancia solo si no es igual. No afecta el rendimiento, solo mantiene la verificación de éxito inmediatamente después de la llamada para encontrar. –

1

Probablemente no deba usar su propia función aquí. Use find() de STL.

Ejemplo:

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

+1

Necesita transferir el iterador a otro vector. – GManNickG

+0

Yeap, ese es exactamente mi problema. El iterador estaría bien, pero no puedo usarlo directamente con otro vector. – sharptooth

3

En este caso, es seguro que desechar la porción sin firmar a menos que el vector puede ser realmente grande.

Quitaría el where.size() a una variable local ya que no cambiará durante la llamada. Algo como esto:

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

Antes que nada, ¿realmente necesita almacenar índices como este? ¿Has buscado en std :: map, lo que te permite almacenar claves => pares de valores?

En segundo lugar, si utilizó iteradores en su lugar, podría devolver std :: vector.end() para indicar un resultado no válido. Para convertir un iterador en un índice, simplemente use

size_t i = it - myvector.begin(); 
2

Algo así, creo. 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 

Ejemplo:

#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's corresponding number is: " << vec2[index] << std::endl; 
    } 
} 

Aunque siento que estoy haciendo algo tonto ...: X Todas las correcciones son bienvenidos, por supuesto.

+0

Lo algo tonto es la cosa find_if_counted_impl. :) Si no tiene un iterador de acceso aleatorio, el índice es bastante inútil para empezar. Si tiene un iterador de acceso aleatorio, puede restar found_it - begin(). También me parece que devolver el tamaño() como el valor "no encontrado" puede ser más útil, por ejemplo, puede estar seguro de que begin() + size() produce un iterador que puede ser útil para algunos fines, mientras que begin() + unsigned (-1) nunca sirve de nada y siempre debe verificarse específicamente. – UncleBens

6

std::vector tiene iteradores de acceso aleatorio. Puede hacer aritmética de puntero con ellos. En particular, este my_vec.begin() + my_vec.size() == my_vec.end() siempre se mantiene. Por lo que podría hacer

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

Como alternativa, siempre hay std::numeric_limits<vector<type>::size_type>::max() para ser utilizado como un valor no válido.

2

Si un vector tiene N elementos, hay N + 1 respuestas posibles para encontrar. std :: find y std :: find_if devuelven un iterador al elemento encontrado O end() si no se encuentra ningún elemento.Para cambiar el código tan poco como sea posible, su función de búsqueda debe devolver la posición equivalente:

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

Me gustaría volver a utilizar std :: find_if, sin embargo.

+0

+1 para devolver 'where.size()'. Tiene perfecto sentido devolverlo. Es consistente con la filosofía de devolver 'where.end()' si la función fuera devolver el iterador en su lugar. – Nawaz

1

Tome un vector de número entero y una clave (que encontramos en el vector) .... Ahora estamos atravesando el vector hasta encontrar el valor clave o el último índice (de lo contrario) ..... Si encontramos la clave, entonces imprima la posición, de lo contrario imprima "-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; 
     } 
+1

por favor explique su código en su publicación –

+1

Tome una matriz de enteros y una clave (que encontramos en la matriz) .... Ahora estamos atravesando el índice de la matriz hasta encontrar el valor clave o el último índice ..... Si encontramos luego imprima el índice, de lo contrario imprima "-1". – rashedcs

+0

@rashedcs por favor edite su respuesta para incluir lo que ha escrito como comentario! –

Cuestiones relacionadas