【发布时间】:2010-10-23 20:07:01
【问题描述】:
我最近开始使用 LINQ,它令人惊叹。我想知道 LINQ 是否允许我在不使用 foreach 的情况下将函数(任何函数)应用于集合的所有元素。类似于 python lambda 函数的东西。
例如,如果我有一个 int 列表,我可以使用 LINQ 为每个元素添加一个常量
如果我有一个 DB 表,我可以使用 LINQ 为所有记录设置一个字段吗?
我正在使用 C#
【问题讨论】:
我最近开始使用 LINQ,它令人惊叹。我想知道 LINQ 是否允许我在不使用 foreach 的情况下将函数(任何函数)应用于集合的所有元素。类似于 python lambda 函数的东西。
例如,如果我有一个 int 列表,我可以使用 LINQ 为每个元素添加一个常量
如果我有一个 DB 表,我可以使用 LINQ 为所有记录设置一个字段吗?
我正在使用 C#
【问题讨论】:
使用 LINQ 执行此操作的惯用方法是处理集合并返回以您想要的方式映射的新集合。例如,要为每个元素添加一个常量,您需要类似
var newNumbers = oldNumbers.Select(i => i + 8);
以一种功能性的方式执行此操作,而不是频繁地改变现有集合的状态,这有助于您以一种更易于阅读且更易于编译器推理的方式分离不同的操作。
如果您确实想要对集合的每个元素应用一个操作(一个具有与集合的实际内容无关的副作用的操作),那么 LINQ 并不是最适合的,尽管您可以使用 Select 伪造它(或编写自己的 IEnumerable 扩展方法,正如许多人所做的那样。)在这种情况下,最好坚持使用 foreach 循环。
【讨论】:
Select 的问题,如果您稍后不对结果进行迭代。
哈哈,伙计,我几个小时前才问过这个问题(有点)......试试这个:
示例:
someIntList.ForEach(i=>i+5);
ForEach() 是 .NET 内置方法之一
这将修改列表,而不是返回一个新列表。
【讨论】:
.ToList().ForEach(...) 就是我所需要的。
解决此问题的常用方法是在IEnumerable<T> 上添加您自己的ForEach 泛型方法。这是我们在MoreLINQ 中得到的:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
source.ThrowIfNull("source");
action.ThrowIfNull("action");
foreach (T element in source)
{
action(element);
}
}
(其中ThrowIfNull 是任何引用类型的扩展方法,这很明显。)
看看这是否是 .NET 4.0 的一部分会很有趣。它与 LINQ 的函数式风格背道而驰,但毫无疑问,很多人觉得它很有用。
一旦你有了它,你就可以写出这样的东西:
people.Where(person => person.Age < 21)
.ForEach(person => person.EjectFromBar());
【讨论】:
Where 部分是功能性的...... ForEach 部分不是那么多,IMO。
你可以试试
var foo = (from fooItems in context.footable select fooItems.fooID + 1);
返回 id 的 +1 列表,您可以对 select 子句中的任何内容使用函数来执行相同操作。
更新:正如 Jon Skeet 所建议的,这是我刚刚发布的代码 sn-p 的更好版本:
var foo = context.footable.Select(foo => foo.fooID + 1);
【讨论】:
你也可以考虑并行,特别是如果你不关心顺序,更关心为每个项目完成某事:
SomeIEnumerable<T>.AsParallel().ForAll( Action<T> / Delegate / Lambda )
例如:
var numbers = new[] { 1, 2, 3, 4, 5 };
numbers.AsParallel().ForAll( Console.WriteLine );
HTH。
【讨论】:
我找到了一些在字典中执行的方法,其中包含我的自定义类方法
foreach (var item in this.Values.Where(p => p.IsActive == false))
item.Refresh();
“this”源自:Dictionary
class MyCustomClass
{
public void Refresh(){}
}
【讨论】:
对于不支持ForEach 的集合,您可以在Parallel 类中使用静态ForEach 方法:
var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
Parallel.ForEach(_your_collection_, options, x => x._Your_Method_());
【讨论】:
或者你可以破解它。
Items.All(p => { p.IsAwesome = true; return true; });
【讨论】: