这个使用 Linq 的 c# 方法有什么问题?
What is wrong with this c# method that uses Linq?
我尝试编写一个方法,给定一个 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();
}
基本上,这行不通。举个简单的例子,like
{1, 5, 3, 8}, n = 7
而结果应该是
{{1}, {5}, {3}, {1, 5}}
实际结果是这样的:
Expected: List<IEnumerable<Int32>> [[1], [5], [3], [1, 5]]
Actual: IEnumerable`1[] []
它生成一个几乎为空的 IEnumerable。我该如何解决?
您可以很容易地使用 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
,依此类推。我们还每次都重新计算总和,而不是保持总计 运行。
我尝试编写一个方法,给定一个 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();
}
基本上,这行不通。举个简单的例子,like
{1, 5, 3, 8}, n = 7
而结果应该是
{{1}, {5}, {3}, {1, 5}}
实际结果是这样的:
Expected: List<IEnumerable<Int32>> [[1], [5], [3], [1, 5]]
Actual: IEnumerable`1[] []
它生成一个几乎为空的 IEnumerable。我该如何解决?
您可以很容易地使用 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
,依此类推。我们还每次都重新计算总和,而不是保持总计 运行。