如果我有一个包含属性fruitName
和numFruits
的对象列表,并且我希望复数fruitName
numFruits
大于1,那么它是否可能通过将Where
和Foreach
链接在一起,在一个声明中做到这一点?
类似的东西:
fruitList.Where(fl => fl.numFruits > 1).ForEach(fl => fl.fruitName = fl.fruitName + "s");
我尝试了以上操作并且无法正常工作。它抱怨System.Collections.Generic.IEnumerable不包含ForEach的定义。
答案 0 :(得分:3)
通常,您希望尽可能使用foreach
语言构造。 Eric Lippert有blog post详细说明原因。
当您进行修改时循环很好,因为它可以更容易地找到这些修改。
foreach (var fl in fruitList.Where(fl => fl.numFruits > 1))
{
fl.fruitName = fl.fruitName + "s";
}
更直接,完成同样的任务。
答案 1 :(得分:2)
如果你真的想要一个单行(它将更难维护)并且想要保持原始列表完整但只修改一些元素,那么你必须使用完整的匿名函数。如果你需要多个语句(一个代码块),你需要包括大括号和语句终止分号,如下所示:
fruitList.ForEach(fl => { fl.fruitName = fl.numFruits > 1 ? fl.fruitName + "s" : fl.fruitName; });
这适用于原始列表(没有子集),并且基本上与结构化foreach
完全相同。
答案 2 :(得分:1)
为什么没有“ForEach”序列运算符扩展方法有一个很好的blog post by Eric Lippert,原因是:
第一个原因是这样做违反了函数式编程 所有其他序列运算符所基于的原则。 显然,调用这种方法的唯一目的是引起副作用 效果。表达式的目的是计算值,而不是计算值 引起副作用。声明的目的是引起一方 影响。这个东西的呼叫网站看起来很像 表达式(但是,诚然,因为该方法是无效的, 表达式只能用在“语句表达式”中 上下文。)与我合作并不合适 序列运算符仅对其副作用有用。
如果您想在一个语句中执行此操作,则可以使用.Select()
var newFruitList = fruitList.Where(fl => fl.numFruits > 1).Select(fl => fl.fruitName + "s");
答案 3 :(得分:0)
与@Tim Schmelter建议的一样,您可以使用ToList()转换为列表,然后对返回的结果使用ForEach方法。虽然ToList()可能会根据过滤器返回一个较短的列表,但原始对象本身会被更改,而fruitList将保持不变。
fruitList.Where(fl => fl.numFruits > 1).ToList().ForEach(fl => fl.fruitName = fl.fruitName + "s");
// fruitList still has all elements
答案 4 :(得分:0)
您可以使用静态Array.ForEach方法更新列表。
Array.ForEach(fruitList.Where(fl => fl.numFruits > 1).ToArray(), x => { x.fruitName += "s"; });
答案 5 :(得分:0)
鉴于"追加s"实际上并没有给你许多成果的正确答案,任何做到这一点的方法都会给你一个错误的答案,无论它做得多好。
考虑使用查找表将单数字映射到复数(反之亦然):
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
private static Dictionary<string, string> fruitLookup =
new Dictionary<string, string>
{
{"blueberry", "blueberries"},
{"peach", "peaches"},
{"apple", "apples"}
};
public static void Main()
{
var fruitList = new List<string> {"blueberry", "peach", "apple"};
// Here is your one-line conversion:
var plurals = fruitList.Select(f => fruitLookup[f]).ToList();
foreach (var p in plurals)
{
Console.WriteLine(p);
}
}
}