从 Linq 查询中提取方法

Extracting a method from a Linq query

我有以下静态方法,其中 return 是 IEnumerable<int> 中所有可能的三元组组合,它们是毕达哥拉斯。例如:对于 int[] array = {1, 2, 3, 4, 5},它将 return new[]{{3, 4, 5}, {4, 3, 5}}.

 public static IEnumerable<IEnumerable<int>> GetPythagoreanNumbers(IEnumerable<int> array)
    {
        return array.SelectMany((a, i) =>
        {
            var inner = array.Skip(i + 1);
            return inner.SelectMany((b, j) =>
                inner.Skip(j + 1)
                    .SelectMany(c => GetTriplePermutations(a, b, c)));
        });
    }

现在,GetTriplePermutations() return 是一个 IEnumerable<IEnumerable<int>>,它表示从收到的 3 个整数(a、b、c)构建的数组集合。基本上,查询 returns 数组中 3 个元素的所有可能排列,从左到右开始。 (例如:{1, 2, 3, 4, 5} => new[]{ {1, 2, 3}, {1, 2, 4}, {1, 2, 5}, {2, 3, 4}, {2, 3, 5}, {3, 4, 5} })。 从查询 return 编辑的所有三元组中,GetTriplePermutations() 只选择满足我条件的那些。

我设法使其正常工作,但是,在重构时,我发现我的查询有点 重复自身,这意味着它应用了相同的连续分机方法模式:

array.SelectMany((a, i)).Skip(x + 1).SelectMany((b, j)).Skip(y + 1)

因此,为了消除重复,我试图以某种方式提取一种方法,该方法允许将代码转换为如下内容:

return OddMethod(array).SelectMany(c => GetTriplePermutations(a, b, c)));

现在,我不知道该怎么做,因为我的部分代码是 returnLinq 查询编辑的。我在想这个 "OddMethod" 的签名应如下所示:

IEnumerable<IEnumerable<int>> OddMethod(int[] array)

,但无法继续前进。有什么想法可以实现 "method extraction" 吗?谢谢! :)

您始终可以定义一个扩展方法来覆盖您的逻辑并使您的代码更具可读性。

阅读更多:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-and-call-a-custom-extension-method

伪代码:

public static IEnumerable<IEnumerable<int>> GetTriplePermutations(tis IEnumerable<int> array)
{
    return array.SelectMany((a, i)).Skip(x + 1).SelectMany((b, j)).Skip(y + 1)
}

您可以使用OddMethod(array).GetTriplePermutations();

调用此函数

经过一些帮助,我找到了我一直在寻找的东西:

 public static IEnumerable<IEnumerable<int>> GetPythagoreanNumbers(IEnumerable<int> array)
        {
            ThrowNullException(array);

            return array.SelectSkip((a, inner) =>
                inner.SelectSkip((b, result) =>
                    result.SelectMany(c => GetTriplePermutations(a, b, c))));
        }

 private static IEnumerable<T> SelectSkip<T>(
            this IEnumerable<int> source,
            Func<int, IEnumerable<int>, IEnumerable<T>> func)
        {
            return source.SelectMany((a, i) =>
            {
                var inner = source.Skip(i + 1);
                return func(a, inner);
            });
        }

不过我想我会继续使用旧版本! :D