webentwicklung-frage-antwort-db.com.de

Wie finde ich eine Elementposition in std :: vector?

Ich muss eine Elementposition in einem std :: vector finden, um sie zum Referenzieren eines Elements in einem anderen vector zu verwenden:

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() gibt jedoch size_t zurück, was einem unsigned -Integraltyp entspricht, der -1 nicht direkt speichern kann. Wie signalisiere ich, dass das Element in einem Vektor nicht gefunden wird, wenn size_t Anstelle von int als Index verwendet wird?

35
sharptooth

Sie können std::numeric_limits<size_t>::max() für Elemente verwenden, die nicht gefunden wurden. Es ist ein gültiger Wert, aber es ist unmöglich, einen Container mit einem solchen Maximalindex zu erstellen. Wenn std::vector Eine Größe von std::numeric_limits<size_t>::max() hat, ist der maximal zulässige Index (std::numeric_limits<size_t>::max()-1), Da Elemente von 0 an gezählt werden.

15

Schauen Sie sich die Antworten für diese Frage an: ngültiger Wert für size_t? . Sie können auch std :: find_if mit std :: distance verwenden, um den Index abzurufen.

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

Müssen Sie zuerst wirklich solche Indizes speichern? Haben Sie in std :: map nachgesehen, um Schlüssel => Wertepaare zu speichern?

Wenn Sie stattdessen Iteratoren verwenden, können Sie zweitens std :: vector.end () zurückgeben, um ein ungültiges Ergebnis anzugeben. Um einen Iterator in einen Index zu konvertieren, verwenden Sie einfach

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

std::vector Hat Iteratoren mit wahlfreiem Zugriff. Sie können mit ihnen Zeiger arithmetisch arbeiten. Insbesondere gilt dieses my_vec.begin() + my_vec.size() == my_vec.end() immer. Also könntest du tun

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

Alternativ kann immer std::numeric_limits<vector<type>::size_type>::max() als ungültiger Wert verwendet werden.

6
sbi

In diesem Fall ist es sicher, den nicht signierten Teil wegzuwerfen, es sei denn, Ihr Vektor kann WIRKLICH groß werden.

Ich würde die where.size () auf eine lokale Variable ziehen, da sie sich während des Aufrufs nicht ändert. Etwas wie das:

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

Sowas finde ich. 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

Beispiel:

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

Obwohl ich das Gefühl habe, etwas Dummes zu tun ...: X Korrekturen sind natürlich willkommen.

2
GManNickG

Wenn ein Vektor N Elemente hat, gibt es N + 1 mögliche Antworten zum Finden. std :: find und std :: find_if geben einen Iterator an das gefundene Element OR end () zurück, wenn kein Element gefunden wurde. Um den Code so wenig wie möglich zu ändern, sollte Ihre Suchfunktion die entsprechende Position zurückgeben:

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

Ich würde trotzdem std :: find_if verwenden.

2
Mark Ruzon

Nehmen Sie einen Vektor aus einer ganzen Zahl und einem Schlüssel (den wir im Vektor finden) .... Jetzt durchlaufen wir den Vektor, bis wir den Schlüsselwert oder den letzten Index gefunden haben (ansonsten) ..... Wenn wir den Schlüssel gefunden haben, drucken Sie die Position Andernfalls geben Sie "-1" aus.

     #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

Sie sollten hier wahrscheinlich keine eigene Funktion verwenden. Verwenden Sie find () from STL .

Beispiel:


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