我有两个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'中的条件。
答案 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()
调用的结果,就像你在原始代码中一样。)