web-dev-qa-db-ja.com

ジェネリックC#コレクションの各値に対して関数を呼び出す

Listコレクションに整数値のコレクションがあります。関数の引数の1つがコレクション値であるコレクション内の各値に対して関数を呼び出したい。 foreachループでこれを行わずに... lambda/linq式でこれを達成する方法はありますか?

次のような... myList.Where(p => myFunc(p.Value));

事前に感謝、-s

48
Stratton

LINQはここでは役に立ちませんが、 List<T>.ForEach を使用できます。

List <T> .ForEachメソッド

リストの各要素で指定されたアクションを実行します。

例:

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

ラムダ式に渡される値はリスト項目です。したがって、この例では、pList<long>の場合、longmyListです。

79
dtb

他のポスターが指摘したように、List<T>.ForEachを使用できます。

ただし、任意のIEnumerable<T>でForEachを使用できる拡張メソッドを簡単に作成できます。

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

つまり、次のことができるようになります。

myList.Where( ... ).ForEach( ... );
21
Winston Smith

うん! List.ForEachを使用できますが、問題はリストに対してのみ機能します(確実にすべてをオンザフライでリストに変更できますが、より少ないコードでもっと楽しく:) )。また、戻り値の型を提供しないAction<>予測を使用する必要があります。

とにかくあなたが望んでいたものに対する答えがあります、あなたはFunc<>で推測したのと同じ方法でそれを可能にすることができますが、以下のような小さなトリックで:

ここですべてをその場で行います:

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をサポートするコレクションで置き換えることができる文字列配列をその場で定義しました。

SecondSelect one Func<string>の内部は、指定された配列の各要素に対して、呼び出されたときに宣言されますx

空の括弧を見て、Func<type**1**, type**2**, ..., type**n**>を定義するときは常に最後の型が戻り型であるため、単にFunc<string>と書くと関数を示すことに注意してください入力パラメーターがなく、戻り値のタイプはstring

与えられた配列(new string[] { "d", "f" })に対して関数を使用したいのは明らかであり、それがパラメーターなしで関数を定義し、Func<>内で同じ変数xを使用した理由です。同じ配列要素を参照します。

Thirdsecond Selectを配置しない場合、2つの関数のコレクションがあります。文字列を返し、すでに最初の配列から入力を取得しています。これを行い、結果をanonymous変数に保持してから、それらの.Invokeメソッドを呼び出すことができます。ここに書きます:

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>();

最後に、結果を配列に変換しました!これで文字列配列ができました!

すみません、長くなります!!役に立つといいのですが。

18
Kharazmi

List.ForEachメソッドを次のように使用できます。

myList.ForEach(p => myFunc(p));
8
Matt Hamsmith

いいえ-リスト内の各アイテムに対して関数を呼び出す場合、リスト内の各アイテムに対して関数を呼び出す必要があります。

ただし、次のように、コードの「ビジネスエンド」を読みやすくするために、IList<T>.ForEach()メソッドを少しの構文糖として使用できます。

items.ForEach(item => DoSomething(item));
5
Neil Barnwell

ForEachメソッドを使用できます。

MSDN:

http://msdn.Microsoft.com/en-us/library/bwabdf9z.aspx

4
tster

List<T>のForEachメソッドを使用するのではなく、IEnumerable<T>を使用する場合(「LINQ:ing」の場合によくあるように)、 MoreLINQ をお勧めします。 = Jon Skeet等により作成.

MoreLINQはForEachを提供し、Pipe(およびその他のメソッドの束)も提供します。これらは各要素に対してアクションを実行しますが、同じIEnumerable<T>(voidと比較して)を返します。

2
Martin R-L

ミニ(まだ完全な)例です。

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);
}
0
granadaCoder