递归迭代器块方法的早期终止

4

我有一个使用递归函数输出数组所有排列的方法:

    /// <summary>
    /// Yields a sequence of all permutations in lexical order
    /// </summary>
    /// <typeparam name="T">Type of item in the input sequence</typeparam>
    /// <param name="input">The initial sequence</param>
    /// <returns>A sequence of all permutations in lexical order</returns>
    public IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> input) 
    {
        var list = input.ToList();
        list.Sort(); // into lexical order

        if (list.Count > 2)
        {
            foreach (var item in list)
            {
                var itemArray = new[] {item};
                T[] otherItems = list.Except(itemArray).ToArray();
                foreach (var permutation in Permute(otherItems))
                    yield return itemArray.Concat(permutation).ToArray();
            }
        }
        else 
        {
            yield return new[] {list[0], list[1]};
            yield return new[] {list[1], list[0]};
        }
    }

然而,当我在 NUnit 测试中运行此函数时,它比我预期的要早终止得多:

    [Test]
    public void Can_print_all_permutations()
    {
        foreach (var p in Permute("123456789"))
        {
            Console.WriteLine(new string(p.ToArray()));
        }
    }

这是测试打印的最后几行(我为了发布目的而将它们用逗号隔开):
349527816, 349527861, 349528167, 349528176, 349528617, 3
突然终止使我认为控制台的缓冲和刷新是问题的一部分,但应该打印的最后一行是987654321,所以我感觉循环提前终止了。如果我在循环中包含一个计算,它会更早地终止(在24...范围内)。我的实现中有什么可以解释这种行为的东西吗?我是否推动了堆栈的极限?

看起来控制台输出被截断了。你尝试过将结果写入文件吗? - Serguei
1
您可能正在测试运行器中受到限制。 - brianpeiris
你可以尝试使用全局计数器来检查是否得到了正确数量的排列。 - Nick Bray
有一种非常好的方法可以检查错误,那就是正确编写测试。与其将内容倒出到控制台上,不如进行断言,例如断言预期的排列数量或者特定的排列是否包含在排列列表中。 - Simone
谢谢,Simone。正是这些技巧让我发现我没有得到我期望的所有结果。 - neontapir
1个回答

5

你使用的测试基础设施很可能有一定的“测试运行最长时间”的限制。列举所有的排列组合确实需要相当长的时间。


我尝试了你的想法,写了一个控制台应用程序,在大约一秒钟内返回了所有362880个值。 - neontapir
2
将我想要执行的计算移动到控制台应用程序中,得出了我预期的结果,评估了所有排列组合。这强烈指向测试框架存在问题。 - neontapir
我在NUnit中打开了错误编号为#1092929的Bug。感谢您的帮助! - neontapir
我下载了NUnit GUI测试运行器。测试成功返回了预期的值,这让我现在怀疑是ReSharper的测试运行器出了问题。 - neontapir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接