Como obter a posição de um determinado elemento no vetor strings, para usá-lo como um índice no vetor ints?

99

Estou tentando obter o índice de um elemento em um vetor de strings, para usá-lo como um índice em outro vetor do inttipo, isso é possível?

Exemplo:

vector <string> Names;
vector <int> Numbers;

 ... 
// condition to check whether the name exists or not
if((find(Names.begin(), Names.end(), old_name_)) != Names.end())  
    {   // if yes
        cout <<"Enter the new name."<< endl;
        cin >> name;
        replace(Names.begin(), Names.end(), old_name_, name);
    }

Agora eu quero obter a posição de old_nameno Namesvetor, para usá-la no acesso a determinado elemento no Numbersvetor. Para que eu possa dizer:

Numbers[position] = 3 ; // or whatever value assigned here.

Tentei usar:

vector <string> :: const_iterator pos;
pos = (find(Names.begin(), Names.end(), old_name_))
Numbers[pos] = 3;

mas obviamente isso não funciona, pois posé do tipo string!

Nour
fonte
Eu acho que isso deve stackoverflow.com/questions/1425349/…
Francesco Vollero
Você deve verificar std :: map ou std :: unordered_map.
Etherealone

Respostas:

158

Para obter a posição de um elemento em um vetor conhecendo um iterador apontando para o elemento, basta subtrair v.begin()do iterador:

ptrdiff_t pos = find(Names.begin(), Names.end(), old_name_) - Names.begin();

Agora é preciso verificar poscontra Names.size()para ver se ele está fora dos limites ou não:

if(pos >= Names.size()) {
    //old_name_ not found
}

iteradores de vetor se comportam de maneira semelhante a ponteiros de array; muito do que você sabe sobre aritmética de ponteiro também pode ser aplicado a iteradores vetoriais.

A partir do C ++ 11, você pode usar std::distanceno lugar da subtração para iteradores e ponteiros:

ptrdiff_t pos = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_));
dasblinkenlight
fonte
Não consigo ver os comentários de @Bob__, talvez excluído? Estou me perguntando por que ptrdiff_té melhor do que size_tptrdiff_t que levantaria um aviso de comparação entre inteiros assinados e não assinados
Hiraku
3
@Hiraku Ele excluiu seu comentário. Ele sugeriu usar ptrdiff_tporque permite armazenar a distância entre qualquer par de iteradores no mesmo contêiner, mesmo em situações em que o resultado é negativo. Se usarmos size_t, devemos ter cuidado para não subtrair um iterador maior de um iterador menor.
dasblinkenlight
Para ser mais preciso, você deve adicionar "#include <algorithm>" (para usar std :: find). O autor da pergunta também omitiu esse "incluir".
Grag2015,
92

Se você deseja um índice, pode usá-lo std::findem combinação com std::distance.

auto it = std::find(Names.begin(), Names.end(), old_name_);
if (it == Names.end())
{
  // name not in vector
} else
{
  auto index = std::distance(Names.begin(), it);
}
Juanchopanza
fonte
8
por que não usar const-iteradores?
dani
-1

Eu sou um iniciante, então aqui está uma resposta para iniciantes. O if no loop for fornece i que pode então ser usado no entanto necessário, como Números [i] em outro vetor. A maioria é fofura, por exemplo, o for / if realmente diz tudo.

int main(){
vector<string>names{"Sara", "Harold", "Frank", "Taylor", "Sasha", "Seymore"};
string req_name;
cout<<"Enter search name: "<<'\n';
cin>>req_name;
    for(int i=0; i<=names.size()-1; ++i) {
        if(names[i]==req_name){
            cout<<"The index number for "<<req_name<<" is "<<i<<'\n';
            return 0;
        }
        else if(names[i]!=req_name && i==names.size()-1) {
            cout<<"That name is not an element in this vector"<<'\n';
        } else {
            continue;
        }
    }
javer
fonte