0

我有这个 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

4 回答 4

3

无论如何,我建议不要使用 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;} 
          });

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

于 2013-08-25T10:02:09.970 回答
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>)。它不是很易读,最好使用非可变方法并根据给定标准生成新列表。

于 2013-08-25T10:10:09.263 回答
1

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

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

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

于 2013-08-25T10:12:45.883 回答
1

就地修改数据并不是 Linq 的强项。Linq 方法通常没有副作用。这就是为什么 .ForEach() 方法不是 Linq 方法并且只为列表定义的原因。

但是,没有什么可以阻止您使用具有副作用的 Linq 函数。所以我不推荐这个解决方案,但是你可以在 select 语句中做任何事情,甚至修改底层列表。还有一个选择重载,它使用元素及其索引作为参数( Select( (element,index) => ... )。

所以你可以用 select 做任何事情,你可以在 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(), ..
于 2013-08-25T10:27:15.720 回答