通过LINQ将函数应用于集合的所有元素

Mid*_*hat 127 .net c# linq

我最近开始使用LINQ并且令人惊叹.我想知道LINQ是否允许我将函数 - 任何函数 - 应用于集合的所有元素,而不使用foreach.像python lambda函数之类的东西.

例如,如果我有一个int列表,我可以使用LINQ为每个元素添加一个常量

如果我有一个数据库表,我可以使用LINQ为所有记录设置一个字段.

我正在使用C#

Jon*_*eet 140

解决此问题的常用方法是添加自己的ForEach通用方法IEnumerable<T>.这是我们在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

(ThrowIfNull任何引用类型的扩展方法都在哪里,这是显而易见的事情.)

看看这是否是.NET 4.0的一部分会很有趣.它违背了LINQ的功能风格,但毫无疑问,很多人发现它很有用.

一旦你有了,你可以写下这样的东西:

people.Where(person => person.Age < 21)
      .ForEach(person => person.EjectFromBar());
Run Code Online (Sandbox Code Playgroud)

  • 我从未真正理解人们必须这样做的冲动.foreach循环对我的眼睛更具可读性; 将获取数据的"功能"部分与对其进行操作的"动作"部分分开有助于阐明算法的结构. (14认同)
  • 是的,我通常更喜欢自己的foreach循环.另一方面,如果你已经有一个委托应用于每个元素,我不确定在一个显式的foreach循环中调用该委托更具可读性.我不会经常使用它,但偶尔它似乎是一个很好的解决方案. (13认同)
  • 执行就地更改而不是返回新类型肯定很糟糕.这会让很多程序员感到困惑.减少的好处是不必嵌套foreach或以其他方式编写丑陋的代码.Oneliners非常易读. (3认同)
  • @Lodewijk:以什么方式使用**具有副作用的方法才能使用?"Where"部分是功能性的......"ForEach"部分并非如此,IMO. (2认同)

mqp*_*mqp 88

使用LINQ执行此操作的惯用方法是处理集合并返回以您想要的方式映射的新集合.例如,要为每个元素添加常量,您需要类似的东西

var newNumbers = oldNumbers.Select(i => i + 8);
Run Code Online (Sandbox Code Playgroud)

以功能方式执行此操作而不是改变现有集合的状态通常可以帮助您以易于阅读和更容易编译器推理的方式分离不同的操作.

如果您实际上想要将一个动作应用于集合的每个元素(具有与集合的实际内容无关的副作用的动作),那么LINQ最适合的不是,尽管您可以伪造它Select(或者IEnumerable像许多人一样编写你自己的扩展方法.)foreach在这种情况下最好坚持使用循环.

  • 在C#中,改变集合的元素是公平的游戏,但是添加或删除集合可能会失败或产生不需要的结果. (12认同)
  • 更不用说在迭代它时改变一个集合是危险的,根本不可能,取决于语言. (3认同)

Jaa*_*ans 42

您也可以考虑并行,特别是如果您不关心序列,而是更多关于为每个项目完成某些事情:

SomeIEnumerable<T>.AsParallel().ForAll( Action<T> / Delegate / Lambda )
Run Code Online (Sandbox Code Playgroud)

例如:

var numbers = new[] { 1, 2, 3, 4, 5 };
numbers.AsParallel().ForAll( Console.WriteLine );
Run Code Online (Sandbox Code Playgroud)

HTH.

  • @YukiSakura不是真的AsParallel().ForAll()的错误 - 危险的位是在多个线程之间使用共享声明,然后"i as string"的转换是传递空键的可能原因.如何分享更完整的代码示例以获得有关如何改进的反馈? (4认同)

and*_*ndy 31

哈哈,伙计,我刚刚问了几个小时前的这个问题(有点)...试试这个:

例:

someIntList.ForEach(i=>i+5);
Run Code Online (Sandbox Code Playgroud)

ForEach() 是内置的.NET方法之一

这将修改列表,而不是返回新列表.

  • 请注意,这仅适用于实际的List <T>集合,除非您已经定义了自己的ForEach方法. (11认同)
  • 我发现大部分时间都添加`.ToList().ForEach(...)`就是我所需要的. (10认同)
  • 我相信mquander指的是ForEach没有在IEnumerable <T>上定义的事实,只是List <T> (3认同)

Jac*_*060 13

或者你可以破解它.

Items.All(p => { p.IsAwesome = true; return true; });
Run Code Online (Sandbox Code Playgroud)

  • 这是黑客攻击"全部"将其变成"ForEach".我有一种不好的感觉,这会误导一些新手认为"全部"意味着"执行所有元素". (9认同)

zme*_*nic 6

对于不支持的集合,ForEach可以ForEachParallel类中使用静态方法:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
Parallel.ForEach(_your_collection_, options, x => x._Your_Method_());
Run Code Online (Sandbox Code Playgroud)