Apply function to all elements of collection through LINQ [duplicate]

To pytanie ma już odpowiedź tutaj:

Ostatnio zacząłem z LINQ i jego niesamowite. Zastanawiałem się, czy LINQ pozwoli mi zastosować funkcję-dowolną funkcję-do wszystkich elementów zbioru, bez użycia foreach. Coś jak python lambda funkcje.

Na przykład, jeśli mam listę int, Mogę dodać stałą do każdego elementu używając LINQ

Jeśli mam tabelę DB, mogę ustawić pole dla wszystkich rekordów używając LINQ.

Używam C #

 119
Author: Midhat, 2009-05-05

8 answers

Powszechnym sposobem podejścia do tego jest dodanie własnej ForEach metody ogólnej na IEnumerable<T>. Oto ten, który mamy w 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);
    }
}

(Gdzie ThrowIfNull jest metodą rozszerzenia na dowolnym typie odniesienia, która robi oczywistą rzecz.)

Ciekawe, czy jest to część. NET 4.0. Jest to sprzeczne z funkcjonalnym stylem LINQ, ale nie ma wątpliwości, że wiele osób uważa go za przydatny.

Kiedy już to masz, możesz pisać takie rzeczy jak:

people.Where(person => person.Age < 21)
      .ForEach(person => person.EjectFromBar());
 130
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-05 06:11:06

Idiomatycznym sposobem na zrobienie tego z LINQ jest przetworzenie kolekcji i zwrócenie nowej kolekcji zmapowanej w pożądany sposób. Na przykład, aby dodać stałą do każdego elementu, potrzebujesz czegoś w rodzaju

var newNumbers = oldNumbers.Select(i => i + 8);

Robienie tego w sposób funkcjonalny zamiast mutowania stanu istniejącej kolekcji często pomaga oddzielić różne operacje w sposób, który jest zarówno łatwiejszy do odczytania, jak i łatwiejszy do rozumowania przez kompilator.

Jeśli jesteś w sytuacji, w której w rzeczywistości chcesz zastosować akcję do każdego elementu kolekcji (działanie z efektami ubocznymi, które nie są powiązane z rzeczywistą zawartością kolekcji), do którego LINQ nie jest najlepiej odpowiedni, chociaż możesz go udawać za pomocą Select (lub napisać własną metodę rozszerzenia IEnumerable, Jak Wiele osób ma.) W takim przypadku najlepiej trzymać się pętli foreach.

 80
Author: mquander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-05 06:03:04

Możesz również rozważyć przejście równolegle, zwłaszcza jeśli nie zależy ci na sekwencji i bardziej na zrobieniu czegoś dla każdego elementu:

SomeIEnumerable<T>.AsParallel().ForAll( Action<T> / Delegate / Lambda )

Na przykład:

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

HTH.

 36
Author: Jaans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 07:38:52

Haha, człowieku, zadałem to pytanie kilka godzin temu (tak jakby)...spróbuj tego:

Przykład:

someIntList.ForEach(i=>i+5);

ForEach() jest jedną z wbudowanych metod. NET

Spowoduje to modyfikację listy, w przeciwieństwie do zwracania nowej.

 26
Author: andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 07:50:54

Albo możesz to rozwalić.

Items.All(p => { p.IsAwesome = true; return true; });
 13
Author: Jack_2060,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 07:51:07

Dla zbiorów, które nie obsługują ForEach można użyć metody statycznej ForEach w klasie Parallel:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
Parallel.ForEach(_your_collection_, options, x => x._Your_Method_());
 5
Author: zmechanic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 15:12:16

Możesz spróbować czegoś takiego

var foo = (from fooItems in context.footable select fooItems.fooID + 1);

Zwraca listę id +1, możesz zrobić to samo używając funkcji do tego, co masz w klauzuli select.

Update: zgodnie z sugestią Jona Skeeta jest to lepsza wersja fragmentu kodu, który właśnie zamieściłem:

var foo = context.footable.Select(foo => foo.fooID + 1);
 1
Author: Drahcir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-05 06:18:16

I found some way to perform in on dictionary contain my custom class methods

foreach (var item in this.Values.Where(p => p.IsActive == false))
            item.Refresh();

Gdzie' to ' pochodzi z: Dictionary

class MyCustomClass 
{
   public void Refresh(){}
}
 -1
Author: user2500321,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 08:26:42