繁体   English   中英

如何找到 std::vector 中的元素位置?

[英]How do I find an element position in 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 ,它对应于无法直接存储-1unsigned整数类型。 当使用size_t而不是int作为索引时,如何发出在向量中找不到该元素的信号?

查看针对此问题提供的答案: Invalid value for 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
}

首先,你真的需要像这样存储索引吗? 您是否研究过 std::map,使您能够存储键 => 值对?

其次,如果您改用迭代器,您将能够返回 std::vector.end() 以指示无效结果。 要将迭代器转换为索引,您只需使用

size_t i = it - myvector.begin();

您可以对未找到的元素使用std::numeric_limits<size_t>::max() 这是一个有效值,但不可能创建具有这样最大索引的容器。 如果std::vector的大小等于std::numeric_limits<size_t>::max() ,则最大允许索引将为(std::numeric_limits<size_t>::max()-1) ,因为元素从 0 开始计数.

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()用作无效值。

在这种情况下,丢弃无符号部分是安全的,除非你的向量可以变得非常大。

我会将 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;
}

如果一个向量有 N 个元素,则查找有 N+1 个可能的答案。 std::find 和 std::find_if 返回一个迭代器到找到的元素或 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。

我想是这样的。 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's corresponding number is: " << vec2[index] << std::endl;
    }
}

虽然我觉得我在做一些愚蠢的事情...... :X 当然,欢迎任何更正。

你可能不应该在这里使用你自己的函数。 使用STL中的find()

例子:


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

取一个整数向量和一个键(我们在 vector 中找到)......现在我们正在遍历向量直到找到键值或最后一个索引(否则)......如果我们找到键然后打印位置,否则打印“-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;  
      }

完全摆脱矢量的概念

template< typename IT, typename VT>
int index_of(IT begin, IT end, const VT& val)
{
    int index = 0;
    for (; begin != end; ++begin)
    {
        if (*begin == val) return index;
    }
    return -1;
}

这将使您更加灵活,并让您使用像这样的结构

int squid[] = {5,2,7,4,1,6,3,0};
int sponge[] = {4,2,4,2,4,6,2,6};
int squidlen = sizeof(squid)/sizeof(squid[0]);
int position = index_of(&squid[0], &squid[squidlen], 3);
if (position >= 0) { std::cout << sponge[position] << std::endl; }

您也可以按顺序搜索任何其他容器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM