在linq中,这对于循环来说是等价的

时间:2013-08-25 09:58:25

标签: linq

我有这个for循环,它在列表中搜索特定值并用新值替换它们。

for (int i = 0; i < Data.Count; i++) {

if (Data[i] > 0 && Data[i] <= 10) {Data[i] = 1;}
else if (Data[i] > 10 && Data[i] < 20) {Data[i] = 2;}      
...
}

我一直在尝试在linq中编写这个函数,我知道它可以用这种方式编写:

var Data2 = Data.Where(x=> x > 0 && x <= 10).Select(y=> y=1).ToList();

我的问题是,有没有办法将此for循环转换为linq形式而无需声明新列表?我的意思是一个linq表单,它在列表中搜索这些值,当它找到它们时,它会相应地替换它们。

4 个答案:

答案 0 :(得分:2)

无论如何,我建议不要使用LINQ:

Enumerable.Range(0,Data.Count)
          .ForEach(x=>{ 
              if (Data[x] > 0 && Data[x] <= 10) {Data[x] = 1;}
              else if (Data[x] > 10 && Data[i] < 20) {Data[x] = 2;} 
          });

这样您就不必声明第二个列表,但代码看起来不如原始列表那么可重复。

答案 1 :(得分:2)

确切的等价物是:

Data
  .Select((e,i) => new { Element = e, Index = i })
  .Where(ei => ei.Element > 0 && ei.Element < 20)
  .ToList()
  .ForEach(ei => Data[ei.Index] = (ei.Element <= 10) ? 1 : 2);

或第二种可能性:查看Save的答案。

然而,它仍然在中间创建一个列表(ForEach仅适用于List<T>)。它不是非常易读,更好地使用非可变方法,只是根据给定的标准生成新的列表。

答案 2 :(得分:1)

比其他解决方案简单得多:

Data = Data.Select(d => (d / 10) + 1)

如果您想要上限,请改用Math.Min((d / 10) + 1, topLimit)

答案 3 :(得分:1)

就地修改数据不是Linq的优势。 Linq方法通常是无副作用的。这就是.ForEach()方法不是Linq方法而只为列表定义的原因。

然而,没有什么能阻止你使用副作用制作Linq功能。 因此我不建议使用此解决方案,但您可以在select语句中执行任何操作,甚至可以修改基础列表。还有一个select重载,它使用元素及其索引作为参数(Select((element,index)=&gt; ...)。

所以你可以选择你可以在for循环中做的任何事情。但我建议使用for循环以便于阅读。

data.Select((d,i)=>
    {if (d > 0 && d <= 10) data[i]=1 else if (d>10 && d<20 data[i]=2;})
    .All(d=>true); // <-- note that you do need some way to consume the IEnumerable
                   // in order to execute the .Select(). You can use ToList(), Count(), ..