代码之家  ›  专栏  ›  技术社区  ›  sharptooth

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

  •  34
  • sharptooth  · 技术社区  · 15 年前

    我需要在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 对应于 unsigned 不能直接存储的整型 -1 . 当使用 尺寸 而不是 int 作为指标?

    9 回复  |  直到 7 年前
        1
  •  15
  •   Kirill V. Lyadvinsky    15 年前

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

        2
  •  59
  •   Undo ptrk    7 年前

    看看这个问题的答案: Invalid value for size_t? . 也可以使用std::find_if with 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
    }
    
        3
  •  17
  •   larsmoa    9 年前

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

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

    size_t i = it - myvector.begin();
    
        4
  •  6
  •   sbi    15 年前

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

        5
  •  3
  •   Jere.Jones    15 年前

    在这种情况下,除非向量真的变大,否则可以安全地去掉无符号部分。

    我将把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;
    }
    
        6
  •  2
  •   GManNickG    15 年前

    我想是这样的。 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当然,欢迎进行任何更正。

        7
  •  2
  •   Mark Ruzon    15 年前

    如果一个向量有n个元素,就有n+1个可能的查找答案。std::find和std::find_如果向找到的元素返回迭代器,或者end()如果找不到元素。要尽可能少地更改代码,find函数应返回等效位置:

    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。

        8
  •  1
  •   Basilevs    15 年前

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

    例子:

    list L;
    L.push_back(3);
    L.push_back(1);
    L.push_back(7);

    list::iterator result=find(l.begin(),l.end(),7); 断言(result==l.end()*result==7);

        9
  •  1
  •   rashedcs    8 年前

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