关于linq:为通用c#集合中的每个值调用一个函数

call a function for each value in a generic c# collection

本问题已经有最佳答案,请猛点这里访问。

在列表集合中有整数值的集合。我想为集合中的每个值调用一个函数,其中函数的参数之一是集合值。不用在foreach循环中执行此操作…有没有一种方法可以通过lambda/linq表达式来实现这一点?

有点像…EDOCX1?0?

事先谢谢,-S


Linq在这里没有帮助,但您可以使用List.ForEach

List.ForEach Method

Performs the specified action on each element of the List.

例子:

1
myList.ForEach(p => myFunc(p));

传递给lambda表达式的值是列表项,因此在本例中,如果myListList,则plong


如其他海报所述,您可以使用List.ForEach

但是,您可以轻松地编写一个扩展方法,允许您在任何IEnumerable上使用foreach。

1
2
3
4
5
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach(T item in source)
        action(item);
}

这意味着你现在可以:

1
myList.Where( ... ).ForEach( ... );


哎呀!您可以使用List.ForEach,但问题是它只适用于list(当然,您可以将所有内容都动态更改为list,但代码越少越有趣)。此外,您还必须使用不提供任何返回类型的Action<>预测。

不管怎样,对于你想要的东西有一个答案,你可以用你对Func<>的猜测,但是用一个小技巧,如下所示:

我会在这里做任何事情:

1
2
3
4
5
6
7
string[] items = (new string[] {"d","f" }).
    Select(x => new Func<string>(() => {
        //Do something here...
        Console.WriteLine(x);
        return x.ToUpper();
    }
)).Select(t => t.Invoke()).ToArray<string>();

这里有一些要点:

首先,我已经动态地定义了一个字符串数组,它可以被任何支持LINQ的集合替换。

其次,在Select的内部,将为给定数组的每个元素声明一个Func,称为x

(看空括号,记住当您定义一个Func时,最后一个类型总是返回类型,所以当您只写Func时,它表示一个没有输入参数的函数,它的返回类型是字符串)

很明显,我们希望在给定数组(new string[] {"d","f" })上使用函数,这就是为什么我定义了一个没有参数的函数,并且我在Func<>内部使用了相同的变量x来引用相同的数组元素。

第三,如果不放置第二个select,那么您有两个返回字符串的函数的集合,并且它们已经从第一个数组获得了输入。您可以这样做,并将结果保存在EDCOX1×22变量中,然后调用它们的EDCOX1 23个方法。我在这里写:

1
2
3
4
5
6
7
var functions = (new string[] {"d","f" }).
       Select(x => new Func<string>(() => {
          //Do something here...
          Console.WriteLine(x);
          return x.ToUpper();
       }));
string[] items = functions.Select(t => t.Invoke()).ToArray<string>();

最后,我把结果转换成一个数组!现在你有一个字符串数组!

对不起,时间太长了!我希望它会有用。


您可以使用list.foreach方法,例如:

1
myList.ForEach(p => myFunc(p));

否-如果要为列表中的每个项调用函数,则必须为列表中的每个项调用函数。

但是,您可以使用IList.ForEach()方法作为一点语法甜头,使代码的"业务端"更具可读性,例如:

1
items.ForEach(item => DoSomething(item));

您可以使用foreach方法:

MSDN:

http://msdn.microsoft.com/en-us/library/bwadbf9z.aspx


如果你不想使用list的foreach方法,而是使用IEnumerable(就像人们经常使用的"linq:ing"),我建议使用jon skeet等人的morelinq方法。

morelinq将为您提供foreach和pipe(以及一系列其他方法),这些方法对每个元素执行操作,但返回相同的IEnumerable(与void相比)。


这里有一个小的(但完整的)例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Employee
{
    public string EmployeeNumber { get; set; }
    public DateTime? HireDate { get; set; }
}
public class EmployeeCollection : List<Employee>
{ }

private void RunTest()
{
    EmployeeCollection empcoll = new EmployeeCollection();
    empcoll.Add(new Employee() { EmployeeNumber ="1111", HireDate = DateTime.Now });
    empcoll.Add(new Employee() { EmployeeNumber ="3333", HireDate = DateTime.Now });
    empcoll.Add(new Employee() { EmployeeNumber ="2222", HireDate = null });
    empcoll.Add(new Employee() { EmployeeNumber ="4444", HireDate = null });

    //Here's the"money" line!
    empcoll.Where(x => x.HireDate.HasValue == false).ToList().ForEach(item => ReportEmployeeWithMissingHireDate(item.EmployeeNumber));

}
private void ReportEmployeeWithMissingHireDate(string employeeNumber)
{
    Console.WriteLine("We need to find a HireDate for '{0}'!", employeeNumber);
}