C# 使用LINQ获取两个值之间整数的倍数序列
好吧,标题很难看,但问题很简单: 我有一个WPF控件,我想在其中显示打印线。我的“视口”有其限制,这些限制(例如,对象坐标中的底部和顶部值)是双倍的 所以我想以5的每一个倍数画一条线。如果我的视口从-8.3变为22.8,我将得到C# 使用LINQ获取两个值之间整数的倍数序列,c#,linq,sequence,C#,Linq,Sequence,好吧,标题很难看,但问题很简单: 我有一个WPF控件,我想在其中显示打印线。我的“视口”有其限制,这些限制(例如,对象坐标中的底部和顶部值)是双倍的 所以我想以5的每一个倍数画一条线。如果我的视口从-8.3变为22.8,我将得到[-5,0,5,10,15,20] 我想用LINQ,它似乎是天生的候选者,但找不到办法 我想大致是这样的: int nlines = (int)((upper_value - lower_value)/step); var seq = Enumerable.Range((
[-5,0,5,10,15,20]
我想用LINQ,它似乎是天生的候选者,但找不到办法
我想大致是这样的:
int nlines = (int)((upper_value - lower_value)/step);
var seq = Enumerable.Range((int)(Math.Ceiling(magic_number)), nlines).Select(what_else);
给定的值是
(双精度)下\u值
,(双精度)上\u值
和(int)步长
可枚举。范围应做到以下几点:
Enumerable.Range(lower_value, upper_value - lower_value)
.Where(x => x % step == 0);
第一个问题是从起点确定步长值的最近因子。一些简单的算法可以推断出这个值:
public static double RoundToMultiple(double value, double multiple)
{
return value - value % multiple;
}
然后,为了在一个范围内创建给定值的所有因子的序列,迭代器块非常适合:
public static IEnumerable<double> FactorsInRange(
double start, double end, double factor)
{
var current = RoundToMultiple(start, factor);
while (start < end)
{
yield return start;
current = current + factor;
}
}
公共静态IEnumerable FactorsInRange(
双起点、双终点、双因素)
{
无功电流=整数倍(启动,系数);
while(开始<结束)
{
收益率-收益率开始;
电流=电流+系数;
}
}
如果您有,那么您可以在不使用显式迭代器块的情况下编写:
public static IEnumerable<double> FactorsInRange(
double start, double end, double factor)
{
return Generate(RoundToMultiple(start, factor),
current => current + factor)
.TakeWhile(current => current < end);
}
公共静态IEnumerable FactorsInRange(
双起点、双终点、双因素)
{
返回生成(RoundToMultiple(开始,因子),
电流=>电流+系数)
.TakeWhile(当前=>当前<结束);
}
尝试以下代码:
double lower_value = -8.3;
double upper_value = 22.8;
int step = 5;
int low = (int)lower_value / step;
int up = (int)upper_value / step;
var tt = Enumerable.Range(low, up - low + 1).Select(i => i * step);
编辑
此代码适用于下限值的所有负值和可被步骤整除的正值。为使其适用于所有其他正值,应进行以下校正:
if (lower_value > step * low)
low++;
为了避免必须枚举每个数字,您必须跳出LINQ:
List<int> steps;
int currentStep = (lower_value / step) * step; //This takes advantage of integer division to "floor" the factor
steps.Add(currentStep);
while (currentStep < upper_value)
{
currentStep += step;
steps.Add(currentStep);
}
列出步骤;
int currentStep=(下限值/步长)*步长//这将利用整数除法来“降低”因子
步骤。添加(当前步骤);
同时(当前步长<上限值)
{
currentStep+=步进;
步骤。添加(当前步骤);
}
快来吧!请注意,您需要首先将下限值/上限值强制转换为整数(使用强制转换的Math.Floor会更好)Range
第二个参数似乎是“count”,而不是“上限值”,是吗?这只适用于整数大小的步长,对于较大的步长值,效率非常低。它也只在小于int.MaxValue
的范围内有效,并且完全在int.MinValue
到int.MaxValue
的范围内,这比双精度
的范围要严格得多。这很漂亮,但是你能想到(很抱歉)某种“一行”吗这个版本?@heltonbiker即使可以,我也不想这么做。我认为这是这个问题最精心设计的解决方案,它既正确又最容易理解、维护和改进。如果您从MoreLinq的Generate
方法开始,那么额外的代码可能会缩减。这是@paqogomez answer的一个由内而外的版本,通过提前一步缩小规模来避免生成后测试。我会尝试一下,很快给你一些反馈。谢谢。这仍然会枚举范围内的每一个数字。@LordTakkera否。可枚举。范围
返回结果中所需的值。@LordTakkera不同之处在于,考虑到步骤
对低
和高
的预linq除法,范围已经更小了。