在列表上使用带有foreach Action的条件lambda语句

为什么我不能做这样的事情?

如果我有一个List myList填充了项目,我希望能够以条件方式对每个成员执行操作:

 myList.ForEach(a => { if (a.Trim().Length == 0) a = "0.0"; }) 

但这不会编译。 我猜它与缺少一个返回值有什么关系?

我试图准备一个字符串列表转换为双打,我希望空项目显示’0.0’所以我可以一次性转换整个列表。

ForEach不可变,它不会以任何方式改变数据结构。

你可以:

  1. 使用索引自己处理循环
  2. 使用.Select和.ToList生成一个新列表(假设您使用的是.NET 3.5)

#1的示例:

 for (Int32 index = 0; index < myList.Count; index++) if (myList[index].Trim().Length == 0) myList[index] = "0.0"; 

使用.NET 3.5和Linq:

 myList = (from a in myList select (a.Trim().Length == 0) ? "0.0" : a).ToList(); 

使用.NET 3.5,不使用Linq语法,而是使用Linq代码:

 myList = myList.Select(a => (a.Trim().Length == 0) ? "0.0" : a).ToList(); 

编辑 :如果您想要生成一个新的双打列表,您也可以使用Linq一次性完成:

 List myDoubleList = (from a in myList select (a.Trim().Length == 0 ? "0" : a) into d select Double.Parse(d)).ToList(); 

请注意,使用“0.0”而不是“0”依赖于小数点是句号。 在我的系统上它不是,所以我用“0”替换它,但更合适的方法是将调用更改为Double.Parse以采用显式数字格式,如下所示:

 List myDoubleList = (from a in myList select (a.Trim().Length == 0 ? "0.0" : a) into d select Double.Parse(d, CultureInfo.InvariantCulture)).ToList(); 

你可能想要的是:

 public static void MutateEach(this IList list, Func mutator) { int count = list.Count; for (int n = 0; n < count; n++) list[n] = mutator(list[n]); } 

这将允许:

 myList.MutateEach(a => (a.Trim().Length == 0) ? "0.0" : a); 

只需将MutateEach方法放在您自己的公共静态类中,并确保您有一个可以找到它的using指令。

是否值得定义这样的东西取决于你使用它的频率。 请注意,它必须是IList上的扩展而不是IEnumerable ,因此我们可以执行更新,这使得它不太适用。

@ daniel-earwicker的MutateEach Extension解决方案是一个很好的解决方案。


但是,为了返回一个新的List ,你可以选择使用自.NET 2.0以来一直存在的List.ConvertAll(Converter(Func))

它不是Linq ,也不是Lambda

 List nodeStringList = new List(new String[] { "", "0.5 ", " 1.1"}); nodeStringList = nodeStringList.ConvertAll((c) => (c.Value.Trim().Length != 0) ? c.Value.Trim() : "0.0"); 

MSDN参考 – List.ConvertAll