web-dev-qa-db-fra.com

Comment trouver une position d'élément dans std :: vector?

J'ai besoin de trouver une position d'élément dans un vecteur std :: pour l'utiliser pour référencer un élément dans n autre vecteur:

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

cependant vector::size() renvoie size_t qui correspond à un type intégral unsigned qui ne peut pas stocker directement -1. Comment puis-je signaler que l'élément n'est pas trouvé dans un vecteur lorsque j'utilise size_t Au lieu de int comme index?

35
sharptooth

Vous pouvez utiliser std::numeric_limits<size_t>::max() pour les éléments introuvables. C'est une valeur valide, mais il est impossible de créer un conteneur avec un tel index max. Si std::vector A une taille égale à std::numeric_limits<size_t>::max(), alors l'index maximum autorisé sera (std::numeric_limits<size_t>::max()-1), Puisque les éléments sont comptés à partir de 0.

15

Jetez un œil aux réponses fournies pour cette question: valeur non valide pour size_t? . Vous pouvez également utiliser std :: find_if avec std :: distance pour obtenir l'index.

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
}
60
Naveen

Tout d'abord, avez-vous vraiment besoin de stocker des indices comme celui-ci? Avez-vous examiné std :: map, vous permettant de stocker des paires clé => valeur?

Deuxièmement, si vous utilisiez des itérateurs à la place, vous seriez en mesure de retourner std :: vector.end () pour indiquer un résultat invalide. Pour convertir un itérateur en index, vous utilisez simplement

size_t i = it - myvector.begin();
17
larsmoa

std::vector Possède des itérateurs à accès aléatoire. Vous pouvez faire de l'arithmétique des pointeurs avec eux. En particulier, cette my_vec.begin() + my_vec.size() == my_vec.end() est toujours valable. Donc tu pourrais faire

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

Comme alternative, il y a toujours std::numeric_limits<vector<type>::size_type>::max() à utiliser comme valeur invalide.

6
sbi

Dans ce cas, il est sûr de supprimer la partie non signée à moins que votre vecteur ne devienne vraiment grand.

Je retirerais where.size () en une variable locale car elle ne changera pas pendant l'appel. Quelque chose comme ça:

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;
}
3
Jere.Jones

Quelque chose comme ça, je pense. 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

Exemple:

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

Bien que j'ai l'impression de faire quelque chose de stupide ...: X Toutes les corrections sont les bienvenues, bien sûr.

2
GManNickG

Si un vecteur a N éléments, il y a N + 1 réponses possibles pour trouver. std :: find et std :: find_if renvoient un itérateur à l'élément trouvé OR end () si aucun élément n'est trouvé. Pour changer le code le moins possible, votre fonction find doit retourner le position équivalente:

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

J'utiliserais quand même std :: find_if.

2
Mark Ruzon

Prenez un vecteur d'entier et une clé (que nous trouvons dans le vecteur) .... Maintenant, nous traversons le vecteur jusqu'à ce que la valeur de la clé ou le dernier index soit trouvé (sinon) ..... Si nous avons trouvé la clé, imprimez la position, sinon, imprimez "-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
rashedcs

Vous ne devriez probablement pas utiliser votre propre fonction ici. Utilisez find () from STL .

Exemple:


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
Basilevs