3

我试图找到一种从同一行中的 Linq 方法访问先前值的方法。

我希望能够在 Linq 中使用这种通用形式:

var values = Enumerable.Range( 1, 100 ).Select( i => i + [last result] );

但是如果没有多行 lambda 并将结果存储在其他地方,我无法找到一种方法来做这样的事情。

所以我在 Linq 中能做的最好的斐波那契总和是:

List<int> calculated = new List<int>( new int[] { 1, 2 });
var fibonacci = Enumerable.Range(2, 10).Select(i =>
    {
        int result = calculated[i - 2] + calculated[i - 1];
        calculated.Add(result);
        return result; // and how could I just put the result in fibonacci?
    }
);

这看起来很丑陋。我可以用更少的代码用常规的 for 循环来做到这一点。

for (int i = 2; i < 10; i++)
{
    calculated.Add(calculated[i - 2] + calculated[i - 1]);
}

似乎如果我能找到一种方法来做到这一点,我可以使用 Linq 来做很多线性规划并总结很多迭代公式。

4

2 回答 2

6

如果您正在寻找一种创建斐波那契序列生成器的方法,最好编写自己的生成器函数,而不是使用 Linq 扩展方法。像这样的东西:

public static IEnumerable<int> Fibonacci()
{
    int a = 1;
    int b = 0;
    int last;

    for (;;) {
        yield return a;

        last = a;
        a += b;
        b = last;
    }
}

Fibonacci().Take(20)然后,您可以将 Linq 方法应用于此可枚举以实现您想要的结果(例如,尝试迭代)。

Linq 扩展方法并不是所有编程问题的解决方案,我只能想象纯 LINQ 斐波那契数列生成器看起来会多么可怕。

于 2012-12-26T21:15:52.777 回答
1

最接近 LINQ 的方法是IEnumerable.Aggregate方法(又名函数式编程中的 fold)。例如,您可以使用它来总结集合的平方,例如:

int sumSquares = list.Aggregate(0, (sum, item) => sum + item * item);

由于在 LINQ 中,值是使用枚举器从集合中检索的,也就是说,它们是一个接一个的,根据定义,没有“上一个项目”的概念。这些物品甚至可以使用一些yield return魔法即时生成和丢弃。也就是说,您总是可以使用一些技巧,例如:

long a= 1;
long b= 1;
var fibonacci = Enumerable.Range(1,20).Select(i => {
  long last= a + b;
  b = a;
  a = last;
  return last;
});

但是当您必须使用和修改外部变量以使 lambda 工作时,您就处于代码异味领域。

于 2012-12-26T21:15:35.257 回答