是否可以要求 LINQ 跳过/离开特定索引

本文关键字:离开 索引 跳过 LINQ 是否 | 更新日期: 2023-09-27 18:32:00

我自己是LINQ的忠实粉丝。简洁的艺术反映在 LINQ 中。同样在.Net中,我们说LINQ比循环领先一步,或者我们可以说LINQ是loops++。

但真的是这样吗?

为什么我之所以做出判断,是因为我试图将其循环代码转换为 LINQ,但对 LINQ 跳过/离开索引感到困惑?

double[] NMD = {3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0 };
for(int i=1; i<NMD.Length-1; i+=2)
   NMD[i] = NMD[i]/10;

在这里,我要求循环从索引 1 开始并在倒数第二个值处停止,并且还跳过值 2。因此,我们可以在 LINQ 中执行此操作。IMO 我不这么认为,但我很高兴被证明是错的。

是否可以要求 LINQ 跳过/离开特定索引

您可以在Select内测试索引并相应地选择操作:

NMD = NMD.Select((x, i) => i % 2 == 1 && i < NMD.Length - 1 ? x / 10 : x).ToArray();
// => { 3, 0.5, 6, 6.5, 34, 0.3, 5, 0.6, 65, 3.4, 3, 0.5, 6, 6.5, 34 }

但是,正如您可能已经通过查看此语句的大小而发现的那样,LINQ 在这里不是概念上的改进,因为您只能使用它创建新序列,而不能改变现有序列。

也就是说,在我看来,for循环很好,实际上更具可读性。与其说"LINQ 是循环++",不如将其细化为"LINQ 是序列生成++"或"只读迭代++"。

如果要有效地使用 LINQ,

则必须以功能更强大的方式(例如,使用不可变的数据结构)重新思考和重新设计代码,而不是仅仅将每个for循环替换为 LINQ 表达式。如果您因此明智地这样做,则可以提高代码的质量,并使交换机并行执行将来的问题更少。

var NMD = new[] {3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0 };
NMD = NMD.Select((n, i) => i % 2 == 1  ? n / 10 : n).ToArray();

您只能使用 NMD.Where((x,i) => i % 2 == 1) 选择具有奇数索引的项目,但您将无法更新数组中的值。

Linq 并不是完成此类任务的最佳工具 - 就地更改数据,而且只是其中的一部分。但如果你真的想这样做,你可以这样做:

NMD = NMD.Select((x, i) =>
{
    if (i < 1 || i >= NMD.Length - 1 || (i % 2)==0)
        return x;
    else
        return x / 10;
}).ToArray();

请记住,使用 linq,您不会更改现有序列,而是将其替换为新序列。