【问题标题】:How to reduce code duplication in this example本例中如何减少代码重复
【发布时间】:2011-03-12 13:31:27
【问题描述】:

我需要遍历一个数字 (xx)。 xx 总是从零开始。我的问题是,如果moveDirection 变量为+1,那么xx 会增加,直到达到range 的正数。如果moveDirection 为-1,则 xx 减小直到达到range 的负值。

在下面的代码中,我首先通过 if 语句测试 moveDirection 来做到这一点,然后我复制了 for 循环,并编辑了每种情况的值。我的代码恰好在 ActionScript3 中,但语言无关紧要。

var p:Point;
var xx:int;

if (moveDirection > 0)
{
    for (xx = 0; xx < range; xx++)
    {
        if (hitTestPoint(xx, yy))
        {
            return true;
        }
    }
}
else 
{
    for (xx = 0; xx > range; xx--)
    {
        if (hitTestPoint(xx, yy))
        {
            return true;
        }
    }
}

有没有更好的方法可以做到这一点,也许不需要复制 for 循环?如果有任何其他建议,将不胜感激。

【问题讨论】:

    标签: language-agnostic optimization for-loop code-duplication


    【解决方案1】:

    另一种可能性:

    int i;
    for (i = abs(range), xx = 0; --i >= 0; xx += moveDirection){
      if (hitTestPoint(xx, yy) return true;
    }
    

    【讨论】:

    • 这个不错。这意味着没有/更少的机会无限循环,我在错误的方向移动到范围。
    【解决方案2】:

    从代码的外观来看,循环运行的方向并不重要——如果hitTestPoint 为范围内的某个值返回true,您只是返回true。如果是这样,另一种可能性是:

    var start:int = min(0, range);
    var stop:int = max(0, range);
    
    for (xx = start; xx!=stop; xx++)
        if (hitTestPoint(xx,yy)
            return true;
    

    【讨论】:

    • 如果 xx 的多个值的 hitTestPoint(xx, yy) 为真,或者特别是如果 hitTestPoint 有副作用,这当然可以改变行为。
    【解决方案3】:

    这是一个 Java 示例 (see also on ideone.com):

    static void go(final int range, final int direction) {
        for (int i = 0; i != direction*range; i += direction) {
            System.out.println(i);
        }       
    }
    

    那么你可以这样做:

            go(5, +1); // 0, 1, 2, 3, 4
            go(5, -1); // 0, -1, -2, -3, -4
    

    如果你想容纳非单元步,最简单的定义第三个参数如下:

    static void go(final int range, final int step, final int direction) {
        for (int i = 0; i < range; i += step) {
            System.out.println(i * direction);
        }       
    }
    

    那么你可以这样做:

            go(10, 3, +1); // 0, 3, 6, 9
            go(10, 3, -1); // 0, -3, -6, -9
    

    【讨论】:

    • 不对; for 循环的第二个子句中的条件也不同。方向的大小可能大于 1。
    【解决方案4】:
    for (xx = 0; xx != range; xx += moveDirection)
    {
        if (hitTestPoint(xx, yy))
        {
            return true;
        }
    }
    

    这假设 moveDirection 将分别为 1 或 -1 表示向上或向下。此外,您必须稍微更改范围才能使 != 正常工作。但是,它确实减少了代码。

    【讨论】:

    • 我会将名称 moveDirection 更改为 movementVector 或其他名称,以明确它存储的内容。 moveDirection 听起来太像枚举之类的了 :)
    • 是的。我只是懒惰并使用预定义的变量,所以我不必自己定义它们。 :P
    • 非常优雅!太感谢了。我总是对可以使用 for 循环(或任何其他循环)的所有不同方式感到惊讶。
    • @Porges :motionVector 听起来太像矢量了。 :) 我更喜欢 moveDirection。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多