Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

call a function for each value in a generic c# collection [duplicate]

I have a collection of integer values in a List collection. I want to call a function for each value in the collection where one of the function's argument is a collection value. Without doing this in a foreach loop... is there a way to accomplish this with a lambda/linq expression?

something like... myList.Where(p => myFunc(p.Value)); ?

thanks in advance, -s

like image 837
Stratton Avatar asked Dec 10 '09 20:12

Stratton


4 Answers

LINQ doesn't help here, but you can use List<T>.ForEach:

List<T>.ForEach Method

Performs the specified action on each element of the List.

Example:

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

The value passed to the lambda expression is the list item, so in this example p is a long if myList is a List<long>.

like image 115
dtb Avatar answered Sep 23 '22 15:09

dtb


As other posters have noted, you can use List<T>.ForEach.

However, you can easily write an extension method that allows you to use ForEach on any IEnumerable<T>

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

Which means you can now do:

myList.Where( ... ).ForEach( ... );
like image 40
Winston Smith Avatar answered Sep 21 '22 15:09

Winston Smith


Yap! You can use List.ForEach but the problem is that works only for list (For sure you can change everything to a List on the fly, but less code more fun :) ). Beside, you have to use Action<> prediction that does not provide any return type.

Anyway there is an answer for what you wanted, you can make it possible in the same way you guessed with Func<> but with a tiny trick as below:

I will do everything here on the fly:

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

There are some points here:

First, I have defined a string array on the fly that can be replaced by any collection that supports LINQ.

Second, Inside of the Select one Func<string> is going to be declared for each element of the given array as it called x.

(Look at the empty parenthesis and remember that when you define a Func<type**1**, type**2**, ..., type**n**> always the last type is the return type, so when you write just Func<string> it indicates a function that has no input parameter and its return type is string)

It is clear that we want to use the function over the given array (new string[] { "d", "f" }), and that's why I define a function with no parameter and also I have used same variable x inside of Func<> to refer to the same array elements.

Third, If you don't put the second Select then you have a collection of two functions that return string, and already they've got their inputs from the first array. You can do this and keep the result in an anonymous variable and then call their .Invoke methods. I write it here:

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

Finally, I've converted the result to an array! Now you have a string array!

Sorry It get long!! I hope it would be useful.

like image 22
Kharazmi Avatar answered Sep 20 '22 15:09

Kharazmi


You could use the List.ForEach method, as such:

myList.ForEach(p => myFunc(p));
like image 9
Matt Hamsmith Avatar answered Sep 22 '22 15:09

Matt Hamsmith