【问题标题】:Elegant way to iterate conditionally forwards or reversed有条件地向前或向后迭代的优雅方式
【发布时间】:2014-04-15 20:25:04
【问题描述】:

我必须正向或反向处理std::vector,具体取决于布尔标志。完成此任务的最优雅方法是什么?在需要反向执行之前,我有:

BOOST_FOREACH(const CType &foo, vec) {
    ...
}

然而,现在我有一个可怕的样子:

for (int i=undoing ? (vec.size()-1) : 0; undoing ? (i >= 0) : (i < vec.size()); undoing ? (i--) : (i++)) {
    const CType &foo = vec[i];
    ...
}

有没有更好的办法?

【问题讨论】:

  • C++11 支持?我想不会。
  • @Yakk:不,不过我还是有兴趣看到这个答案。
  • 对 (unsigned i=undoing ? (vec.size()-1) 的代码进行最小化简化:0; i

标签: c++ loops boost iterator reverse


【解决方案1】:

我不知道人们会称之为优雅,但有:

auto do_it = [](const CType& elem)
             {
                 ...
             };
if (iterate_forward) {
    std::for_each(vec.begin(), vec.end(), do_it);
}
else {
    std::for_each(vec.rbegin(), vec.rend(), do_it);
}

【讨论】:

  • 哦,有趣。我更喜欢这个而不是最高投票的答案,因为我不必自己重新实现循环部分。
  • 是的,我同意这样更好。您应该尽可能使用 STL 算法。当然 lambda 表达式可以替换为一元函数以与 C++98 编译器一起使用。
【解决方案2】:

添加一个与正向迭代器或反向迭代器一起使用的模板函数。根据undoing 的值使用适当的迭代器调用函数。

template <typename Iterator>
void doStuff(Iterator iter, Iterator end)
{
   for ( ; iter != end; ++iter )
   {
      // Do stuff
   }
}

if ( undoing )
{
   doStuff(vec.rbegin(), vec.rend());
}
else
{
   doStuff(vec.begin(), vec.end());
}

【讨论】:

    【解决方案3】:

    如何保持循环从 0 到 vector.size 运行,但按您需要的方向读取数组。

    int idx;
    for (int i =0; i < vec.size(); i ++)
    {
       if (undoing) // assuming going forward
         idx = i;
       else // going backwards
         idx = vec.size() - i - 1;
    
      const CType &foo = vec[idx];
    }
    

    【讨论】:

      【解决方案4】:

      您也可以使用基于 Boost.Range 的解决方案。它类似于已经提出的使用 STL 算法的算法。

      #include <boost/range/adaptor/reversed.hpp>
      #include <boost/range/algorithm/for_each.hpp>
      
      // In C++11 lambda expression can be used instead
      struct my_fun
      {
          void operator()(const CType& elem) const
          {
              /*...*/
          }
      };
      
      /*...*/
      
      using namespace boost::adaptors;
      
      if ( iterate_forward )
          boost::for_each(my_vect, my_fun());
      else
          boost::for_each(my_vect | reversed, my_fun());
      

      【讨论】:

        猜你喜欢
        • 2017-07-09
        • 2017-03-07
        • 2013-04-01
        • 2017-05-25
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多