【问题标题】:Iterating from 1..n or n..1 conditionally in C++在 C++ 中有条件地从 1..n 或 n..1 迭代
【发布时间】:2014-06-11 11:39:59
【问题描述】:

我的代码如下所示:

bool var = some condition...
if( var )
{
     for( int i=0; i<10; ++i )
     {
         //execute some code ...
     }
}
else
{
     for( int i=9; i>=0; --i )
     {
         //execute some other code...
     }
}

但是,需要在 for 循环中执行的代码几乎完全相同,所以我不想写两次。我知道我可以这样做:

bool var = some condition...
for( int i = (var ? 0 : 9 ); (var ? i<10 : i>=0 ); (var ? ++i : --i ) )
{
    //Execute my code
}

但这是一个非常不优雅的解决方案。

有没有一种更简洁、更优雅的方式来做到这一点?我检查了 std::iterator 但我认为这不是我需要的。

【问题讨论】:

  • 使用迭代器需要使用同时具有正向和反向迭代器的容器,但其中很多都有。

标签: c++ for-loop conditional-statements


【解决方案1】:

这在我看来有点像迭代,所以让我们尝试编写一个函数来帮助我们:

void incr(int& i) { ++i; }
void decr(int& i) { --i; }

template <typename Iter, typename Incr>
void do_work(Iter start, Iter finish, Incr incr)
{
    for(Iter i = start, i != finish; incr(i))
    {
        // Do your code.
    }
}

bool var = some condition...
if( var )
{
    do_work(0, 10, &incr);
}
else
{
    do_work(9, -1, &decr);
}

【讨论】:

    【解决方案2】:

    尽量减少重复代码是明智之举,但这并不意味着您的解决方案需要一行一行。只需以有意义且易读的方式写出逻辑即可。包括 cmets 来解释你在做什么以及为什么。

    bool var = some condition...
    int start = 0;
    int end = 9;
    int increment = 1;
    if (!var)
    {
        // Reverse direction
        start = 9;
        end = 0;
        increment = -1;
    }
    
    // Loop (forwards if var; reversed if !var)
    for (int i = start; i != end; i += increment)
    {
    } 
    

    【讨论】:

      【解决方案3】:

      你可以使用类似的东西。

      for(int j = 0; j < 10; ++j) { // always increases
          int i = var ? j : 10 - 1 - j;
          //go
      }
      

      【讨论】:

        【解决方案4】:

        您在这里关注的是错误的问题。如果你有一个方向标志,不要全神贯注于迭代变量是正确的。只需按要求解释即可:

        for (int i = 0; i < n; ++i)
        {
           int j = var ? i : n - 1 - i;
        
           // j goes from 0..n-1 or n-1..0
        }
        

        除非您执行数十亿次这样的调用,否则辅助变量的开销将是微不足道的。

        【讨论】:

        • 不知道自己怎么没想到,这么简单。
        【解决方案5】:

        您可以将循环体分解为一个函数/方法,并传递足够的上下文以使操作发生。如果循环体主要使用this 上的字段,则使其成为一种方法应该相当容易。否则,您不需要比当前循环更多的参数。

        如果您使用的是 C++11,您可以将其实现为捕获任何必要信息的 lambda,并从每个循环中调用 lambda(以免函数松散)。不过,使用可以独立测试的函数或方法是个好主意。

        循环内的代码是否依赖于迭代器的值,如果是,如何?您可能能够以一种巧妙的方式使用一些基本的数学运算,例如将开始/结束转换为始终为 1..n,或使用abs 和负数。这会给你留下一个循环,并且将主体移出一个函数并不是绝对必要的。

        【讨论】:

        • +1 总是从 0 到 9 循环,并使用一些额外的变量 int internal_i = var ? i : 9-i
        猜你喜欢
        • 2015-10-08
        • 2017-10-30
        • 1970-01-01
        • 1970-01-01
        • 2018-04-11
        • 1970-01-01
        • 2014-02-06
        • 2012-11-20
        • 1970-01-01
        相关资源
        最近更新 更多