这个循环可以写得更简洁吗?

时间:2013-03-22 19:18:57

标签: c#

我有两个queues,比方说A和B,我在其上执行以下算法:

while (queueA.Count > 0)
{
    var elemA = queueA.Peek();
    var elemB = queueB.Peek();
    if (AreSimilar(elemA, elemB))
    {
        Debug.Assert(elemA.SomeProperty == elemB.SomeProperty);
        queueA.Dequeue();
        queueB.Dequeue();
    }
    else
    {
        break;
    }    
}

有些东西告诉我这可以写得更简洁; Peek()和Dequeue()可能在一个操作中组合,因为Dequeue()返回与Peek()相同的元素,if语句可能与while语句融合,避免显式中断。我只是没有看到如何完全保留相同的行为,即我不想删除元素,除非它满足'if'中的条件。

3 个答案:

答案 0 :(得分:4)

您可以尝试使用此代码将分配移动到AreSimilar

的调用中
QueueElement elemA, elemB
while (queueA.Count > 0 && AreSimilar(elemA = queueA.Peek(), elemB = queueB.Peek())) {
    Debug.Assert(elemA.SomeProperty == elemB.SomeProperty);
    queueA.Dequeue();
    queueB.Dequeue();
}

请注意,这不一定更具可读性。事实上,就可读性而言,您的版本非常好。我唯一要做的就是颠倒条件以减少嵌套,但我会把其他一切都留在原处:

while (queueA.Count > 0)
{
    var elemA = queueA.Peek();
    var elemB = queueB.Peek();
    if (!AreSimilar(elemA, elemB))
    {
        break;
    }
    Debug.Assert(elemA.SomeProperty == elemB.SomeProperty);
    queueA.Dequeue();
    queueB.Dequeue();
}

答案 1 :(得分:2)

A和B的相似之处是什么?如果概率很高,你可以随时运行w /假定的常见场景并弹出它们(或者队列)它们相似它们会相似然后只是担心如果它们不相似就重新推它们......

答案 2 :(得分:1)

您可以借助方法简化循环,但您可能会考虑这种作弊行为:

static bool DequeuePairIf<T>(
    Func<T, T, bool> predicate,
    Queue<T> queueA,
    Queue<T> queueB)
{
    if (queueA.Count != 0 &&
        queueB.Count != 0 &&
        predicate(queueA.Peek(), queueB.Peek())
    ) {
        queueA.Dequeue();
        queueB.Dequeue();

        return true;
    }

    return false;
}

然后你的循环变为:

while (DequeuePairIf(AreSimilar, queueA, queueB)) { }

但我怀疑这种重构是否有助于提高可读性或损害它。一件事,它比原始代码大得多。另一方面,较小的代码并不总是更易读。

(我在这里删除了断言以简化逻辑。如果你仍然需要断言,那么你必须保存Peek()调用的结果,就像你在原始代码中一样。)