Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ获取两个值之间整数的倍数序列_C#_Linq_Sequence - Fatal编程技术网

C# 使用LINQ获取两个值之间整数的倍数序列

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((

好吧,标题很难看,但问题很简单:

我有一个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((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除法,范围已经更小了。