将一个丑陋的循环重构到LINQ中

本文关键字:循环 重构 LINQ 一个 | 更新日期: 2023-09-27 18:14:36

我有以下和平的代码,将int因子化为素数:

    private static IEnumerable<int> Factor(int input)
    {
        IList<int> result = new List<int>();
        while (true)
        {
            var theSmallestDivisor = GetTheSmallestDivisor(input);
            if (theSmallestDivisor == 0)
            {
                result.Add(input);
                return result;
            }
            result.Add(theSmallestDivisor);
            input = input/theSmallestDivisor;
        }
    }

我正在寻找如何改进它的提示,可能使用LINQ。

将一个丑陋的循环重构到LINQ中

这是一个迭代器版本:

private static IEnumerable<int> Factor(int input)
{
    while (true)
    {
        var theSmallestDivisor = GetTheSmallestDivisor(input);
        if (theSmallestDivisor == 0)
        {
            yield return input;
            yield break;
        }
        yield return theSmallestDivisor;
        input = input / theSmallestDivisor;
    }
}

LINQ只会在这种情况下降低代码的可读性。

LINQ的操作符主要用于从现有列表生成新列表。例如

IEnumerable<B> LinqOperator(this IEnumerable<A> list, ...)

不是为了从头开始生成列表,而是为了尝试这样做。

但是,由于您返回的是IEnumerable,您不妨将其设置为lazy:

private static IEnumerable<int> Factor(int input)
{
    while (true)
    {
        var theSmallestDivisor = GetTheSmallestDivisor(input);
        if (theSmallestDivisor == 0)
        {
            yield return input;
            yield break;
        }
        yield return theSmallestDivisor;
        input = input/theSmallestDivisor;
    }
}
public IEnumerable<int> GetFactors(int input)
{
    int first = Primes()
        .TakeWhile(x => x <= Math.Sqrt(input))
        .FirstOrDefault(x => input % x == 0);
    return first == 0
            ? new[] { input }
            : new[] { first }.Concat(GetFactors(input / first));
}