【问题标题】:C++ - Iterating over std::vector<> returned from find_ifC++ - 迭代从 find_if 返回的 std::vector<>
【发布时间】:2014-02-03 17:29:45
【问题描述】:

我正在学习 C++,所以我觉得这应该是一个非常简单的答案——但我似乎找不到。所以如果我太天真了,我提前道歉。

我有一个std::vector&lt;int&gt; of 值,我正在尝试查找 odd 值的索引。

我正在关注here的代码:

(以下重复):

// find_if example
#include <iostream>     // std::cout
#include <algorithm>    // std::find_if
#include <vector>       // std::vector

bool IsOdd (int i) {
  return ((i%2)==1);
}

int main () {
  std::vector<int> myvector;

  myvector.push_back(10);
  myvector.push_back(25);
  myvector.push_back(40);
  myvector.push_back(55);

  std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
  std::cout << "The first odd value is " << *it << '\n';

  return 0;
}

本示例打印第一个奇数值。 我如何扩展它以给我myvector 中每个奇数值的索引值?这是正确的方法吗?

【问题讨论】:

    标签: c++ vector iterator


    【解决方案1】:
    // find_if example
    #include <iostream>     // std::cout
    #include <algorithm>    // std::find_if
    #include <vector>       // std::vector
    
    bool IsOdd (int i) {
      return ((i%2)==1);
    }
    
    int main () {
      std::vector<int> myvector;
    
      myvector.push_back(10);
      myvector.push_back(25);
      myvector.push_back(40);
      myvector.push_back(55);
    
    
      std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd); 
      std::cout << "ODD values are: " << std::endl;     
    
      while(it != myvector.end() ){
    
        std::cout << *it  << " in position " << (it - myvector.begin())  << '\n';
        it = std::find_if (++it, myvector.end(), IsOdd); 
      }
      return 0;
    }
    

    编辑:将it+1 更改为++it 请参阅@David Rodríguez - dribeas 评论如下。

    【讨论】:

    • 我需要关于距离的信息(it - myvector.begin())。谢谢!完整阅读本文确实有助于我的理解。
    • nit:std::find_if(++it,...
    • @DavidRodríguez-dribeas 抱歉,对于这种情况,++ 有什么优势?是否存在运算符'+'未重载的情况?我不明白。谢谢。
    • it+1 需要随机访问迭代器,这是比++it 更强的要求(只需要前向迭代器)。在这种特殊情况下,这很好,因为std::vector&lt;&gt;::iterator 是随机访问,但使用++it 使解决方案对其他容器可行。
    • it - myvector.begin() 也称为distance(myvector.begin(), it)distance 可能有助于更好地了解正在发生的事情。
    【解决方案2】:

    您可以递增it 并将其用作进一步迭代的起点:

    std::cout << "odd values: ";
    auto it = myvector.begin();
    while(it != myvector.end())
    {
       it = std::find_if (it, myvector.end(), IsOdd);
       if(it == myvector.end()) break;
       std::cout << *it << ' ';
       ++it;
    }
    std::cout << endl;
    

    一种更加面向算法的方法,利用copy_if,将输出向量作为结果容器:

    std::vector<int> results;
    std::copy_if(myvector.begin(), myvector.end(), std::back_inserter(results), IsOdd);
    

    现在结果包含奇数值。 (注意后面:inserter在&lt;iterator&gt;标头中)

    【讨论】:

    • 您可以使用while(true) 简化循环。这样我们就不会在每次循环迭代中检查 end 两次。
    【解决方案3】:

    您可以通过减去序列的开头来找到向量迭代器(更一般地说,任何随机访问迭代器)的索引:

    std::cout << "The index is " << (it - myvector.begin()) << '\n';
    

    更一般地说,有一个std::distance 函数可以为您提供前向迭代器之间的距离。您可以使用它,例如,如果您的容器是 list;但您可能不想这样做,因为它会慢得多。

    要查找所有奇数,您需要一个循环来再次调用find,从刚刚找到的那个元素之后的元素开始。

    【讨论】:

      【解决方案4】:

      改变这两行:

      std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
      std::cout << "The first odd value is " << *it << '\n';
      

      变成类似:

      std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
      while ( it != myvector.end() ) {
          std::cout << "The next odd value is " << *it << '\n';
          it = std::find_if (++it, myvector.end(), IsOdd);
      }
      

      【讨论】:

        【解决方案5】:

        你需要一个循环。标准库的迭代器算法设计使这非常容易:

        #include <iterator>
        
        for (auto it = myvector.begin();
             (it = std::find_if(it, myvector.end(), IsOdd)) != myvector.end(); )
        {
            std::cout << *it << " at index " << std::distance(myvector.begin(), it) << "\n";
        }
        

        【讨论】:

        • 手推车挑战:你能用远程操作完成这项工作吗? :)
        • @LightnessRacesinOrbit:“我可以”,还是“我会推荐它”吗? :-)
        【解决方案6】:

        一个不错的紧凑解决方案可能是:

        #include <algorithm>
        #include <iostream>
        #include <iterator>
        #include <vector>
        
        int main() {
          std::vector<int> const v{1,4,9,11,2,7,8};
          std::cout << "Odd values at indices";
          for(auto b=begin(v), i=b, e=end(v);
              (i=find_if(i,e,[](int a){return a%2==1;})) != e;
              ++i)
            std::cout << ' ' << distance(b,i);
          std::cout.flush();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-01-14
          • 2014-11-08
          • 2012-05-07
          • 2022-09-30
          • 2020-08-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多