Reputation: 243
For my application, I have built an iterator and I need to use each of the values it yields along with the previous one.
For example, consider the following iterator, that yields the first terms of the Fibonacci sequence:
public static IEnumerable<int> GetFibonacciNumbers(int count)
{
int a = 0;
int b = 1;
int i = 0;
while (i < count)
{
yield return a;
int temp = a;
a = b;
b = temp + b;
i++;
}
}
Now I want to use this enumerator to compute increasingly accurate estimates of the golden ratio, which means I need to use the yielded value along with the previous one. The following approach kind of works:
static void Main(string[] args)
{
int fib0 = 0;
foreach (int fib1 in GetFibonacciNumbers(10))
{
var phi = (double)fib1 / fib0;
Console.WriteLine(phi);
fib0 = fib1;
}
}
The issues are that the first value for phi
is wrong, as the first value for fib0
used isn't actually part of the sequence.
Upvotes: 1
Views: 205
Reputation: 49095
Just return both the current and previous values from your iterator:
public static IEnumerable<(int prevValue, int currentValue)> GetFibonacciNumbers(int count)
{
int a = 0;
int b = 1;
int i = 0;
while (i < count)
{
yield return (a, b);
int temp = a;
a = b;
b = temp + b;
i++;
}
}
The above uses C# 7.0 Tuple Syntax, but you can easily convert it to use a regular Tuple<int, int>
as well.
Upvotes: 2
Reputation: 239646
Haim770's answer is correct if you want to modify your generator. However, you might also want to use a general purpose method that you can then reuse with any IEnumerable<T>
:
public static IEnumerable<(T prevValue, T currentValue)> OverlappingPairs<T>(IEnumerable<T> source)
{
bool first = true;
T previous = default;
foreach (var item in source)
{
if (!first)
yield return (previous, item);
first = false;
previous = item;
}
}
(And of course, if you add this
before the parameter and put it in a static class, it'll work as an extension method)
Upvotes: 1
Reputation: 62472
You can have the enumerating function keep track of the previous and current values and return them as a tuple. For example, in the fibonacci example it would be something like this:
static IEnumerable<(int Previous, int Current)> GetFibonacciNumbers(int count)
{
var (previous, current) = (0, 1);
for(int i = 0; i < count; i++)
{
yield return (previous, current);
(previous, current) = (current, previous + current);
}
}
Upvotes: 1
Reputation: 91
Some fibonacci sequences start with 1 and 1 instead of 0 and 1. So maybe that could solve your problem.
Upvotes: 0