【问题标题】:What is wrong with this c# method that uses Linq?这个使用 Linq 的 c# 方法有什么问题?
【发布时间】:2020-10-08 18:47:22
【问题描述】:

我尝试编写一个方法,给定一个 int Enumerable 和一个 int 变量(我们称之为 n),它生成所有总和小于 n 的子序列。

事情是这样的:

public static IEnumerable<IEnumerable<int>> SubSWithSumSmallerThanN(this IEnumerable<int> intEnum, int n)
    {
        var numbers = intEnum.ToList();
        return Enumerable
            .Range(1, numbers.Count)
            .SelectMany(length => Enumerable.Range(0, numbers.Count - length + 1)
                                            .Select(x => numbers.TakeWhile(y => numbers.IndexOf(y) > x && numbers.IndexOf(y) < x + length)))
                                            .Where(x => x.Sum() <= n)
            .ToArray();
    }

基本上,这是行不通的。举个简单的例子,比如

{1, 5, 3, 8}, n = 7

而结果应该是

{{1}, {5}, {3}, {1, 5}}

实际结果是这样的:

Expected: List<IEnumerable<Int32>> [[1], [5], [3], [1, 5]]
Actual:   IEnumerable`1[] []

它生成一个大部分为空的 IEnumerable。我该如何解决?

【问题讨论】:

  • 你调试了吗?我害怕想到你的算法的复杂性是什么,所有这些IndexOfs(加上当你有重复的数字时它会停止工作)
  • 为什么预期结果中不存在 {1,3}?
  • 因为它不是一个序列。要获得 {1, 3},您必须跳过 5。

标签: c# linq ienumerable


【解决方案1】:

您可以很容易地使用for 循环编写解决方案:

public static IEnumerable<IEnumerable<int>> SubsequencesLessThen(IReadOnlyList<int> input, int limit)
{
    for (int i = 0; i < input.Count; i++)
    {
        int sum = 0;
        for (int j = i; j < input.Count; j++)
        {
            sum += input[j];
            if (sum >= limit)
                break;

            yield return input.Skip(i).Take(j - i + 1);
        }
    }
}

仅使用 linq 我能想到的最接近的等价物是:

public static IEnumerable<IEnumerable<int>> SubsequencesLessThen2(IReadOnlyList<int> input, int limit)
{
    return from i in Enumerable.Range(0, input.Count)
        from j in Enumerable.Range(i, input.Count - i)
        let elements = input.Skip(i).Take(j - i + 1)
        let sum = elements.Sum()
        where sum <= limit
        select elements;
}

这有点贵:我们不会在发现总和超过限制时立即停止,所以这将计算1+5 然后1+5+3 然后1+5+3+8 然后5+3,等等在。我们还每次都重新计算总和,而不是保持一个运行总计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多