web-dev-qa-db-fra.com

Appliquer la fonction à tous les éléments de la collection via LINQ

J'ai récemment commencé avec LINQ et son incroyable. Je me demandais si LINQ me permettrait d'appliquer une fonction - n'importe quelle fonction - à tous les éléments d'une collection, sans utiliser foreach. Quelque chose comme python fonctions lambda.

Par exemple, si j'ai une liste int, puis-je ajouter une constante à chaque élément en utilisant LINQ

Si j'ai une table de base de données, puis-je définir un champ pour tous les enregistrements utilisant LINQ.

J'utilise C #

126
Midhat

Une méthode courante consiste à ajouter votre propre méthode générique ForEach sur IEnumerable<T>. Voici celui que nous avons dans 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);
    }
}

(Où ThrowIfNull est une méthode d'extension sur tout type de référence, ce qui rend la chose évidente.)

Il sera intéressant de voir si cela fait partie de .NET 4.0. Cela va à l'encontre du style fonctionnel de LINQ, mais il ne fait aucun doute que beaucoup de gens le trouvent utile.

Une fois que vous avez cela, vous pouvez écrire des choses comme:

people.Where(person => person.Age < 21)
      .ForEach(person => person.EjectFromBar());
136
Jon Skeet

La façon idiomatique de le faire avec LINQ est de traiter la collection et de renvoyer une nouvelle collection mappée à la manière souhaitée. Par exemple, pour ajouter une constante à chaque élément, vous voulez quelque chose comme

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

Effectuer cette opération de manière fonctionnelle au lieu de muter fréquemment l'état de votre collection existante vous aide à séparer des opérations distinctes d'une manière à la fois plus facile à lire et à raisonner pour le compilateur.

Si vous souhaitez réellement appliquer une action à chaque élément d'une collection (une action dont les effets secondaires ne sont pas liés au contenu réel de la collection), ce n'est pas vraiment ce à quoi LINQ convient le mieux, bien que pourrait le simuler avec Select (ou écrire votre propre méthode d’extension IEnumerable, comme beaucoup de gens l’a fait.) Il est probablement préférable de s'en tenir à une boucle foreach dans ce cas.

87
mqp

Vous pouvez également envisager d’aller en parallèle, en particulier si vous ne vous souciez pas de la séquence et plus du fait de faire quelque chose pour chaque article:

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

Par exemple:

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

HTH.

39
Jaans

haha, mec, je viens de poser cette question il y a quelques heures (genre de) ... essayez ceci:

exemple:

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

ForEach() est l'une des méthodes .NET intégrées

Cela modifiera la liste, par opposition à en renvoyer une nouvelle.

30
andy

Ou vous pouvez le pirater.

Items.All(p => { p.IsAwesome = true; return true; });
12
Jack_2060

Pour les collections qui ne prennent pas en charge ForEach, vous pouvez utiliser la méthode statique ForEach dans Parallel class:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 1 };
Parallel.ForEach(_your_collection_, options, x => x._Your_Method_());
5
zmechanic

Vous pouvez essayer quelque chose comme

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

Retourne une liste d'id +1, vous pouvez faire la même chose en utilisant une fonction pour tout ce que vous avez dans la clause select.

Mise à jour: comme l'a suggéré Jon Skeet, il s'agit d'une meilleure version de l'extrait de code que je viens de publier:

var foo = context.footable.Select(foo => foo.fooID + 1);
1
Drahcir