迭代 IEnumerable 的 2 个连续值
Iterate on 2 consecutive values of an IEnumerable
对于我的应用程序,我构建了一个迭代器,我需要将它产生的每个值与前一个一起使用。
例如,考虑以下迭代器,它产生斐波那契数列的第一项:
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++;
}
}
现在我想使用这个枚举器来计算越来越准确的黄金比例估计值,这意味着我需要将产生的值与前一个一起使用。以下方法有效:
static void Main(string[] args)
{
int fib0 = 0;
foreach (int fib1 in GetFibonacciNumbers(10))
{
var phi = (double)fib1 / fib0;
Console.WriteLine(phi);
fib0 = fib1;
}
}
问题是 phi
的第一个值是错误的,因为使用的 fib0
的第一个值实际上不是序列的一部分。
一些斐波那契数列以 1 和 1 开头,而不是 0 和 1。所以也许这可以解决您的问题。
您可以让枚举函数跟踪先前值和当前值,并将它们 return 作为元组。例如,在斐波那契示例中,它将是这样的:
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);
}
}
只需 return 来自迭代器的当前值和先前值:
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++;
}
}
以上使用 C# 7.0 Tuple Syntax,但您也可以轻松地将其转换为使用常规 Tuple<int, int>
。
如果您想修改生成器, 是正确的。但是,您可能还想使用一种通用方法,然后可以将其重复用于任何 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;
}
}
(当然,如果您在参数前添加this
并将其放在静态class中,它将作为扩展方法工作)
对于我的应用程序,我构建了一个迭代器,我需要将它产生的每个值与前一个一起使用。
例如,考虑以下迭代器,它产生斐波那契数列的第一项:
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++;
}
}
现在我想使用这个枚举器来计算越来越准确的黄金比例估计值,这意味着我需要将产生的值与前一个一起使用。以下方法有效:
static void Main(string[] args)
{
int fib0 = 0;
foreach (int fib1 in GetFibonacciNumbers(10))
{
var phi = (double)fib1 / fib0;
Console.WriteLine(phi);
fib0 = fib1;
}
}
问题是 phi
的第一个值是错误的,因为使用的 fib0
的第一个值实际上不是序列的一部分。
一些斐波那契数列以 1 和 1 开头,而不是 0 和 1。所以也许这可以解决您的问题。
您可以让枚举函数跟踪先前值和当前值,并将它们 return 作为元组。例如,在斐波那契示例中,它将是这样的:
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);
}
}
只需 return 来自迭代器的当前值和先前值:
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++;
}
}
以上使用 C# 7.0 Tuple Syntax,但您也可以轻松地将其转换为使用常规 Tuple<int, int>
。
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;
}
}
(当然,如果您在参数前添加this
并将其放在静态class中,它将作为扩展方法工作)