131 votes

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 les fonctions python 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 #

144voto

Jon Skeet Points 692016

Une manière commune d'aborder cette question consiste à ajouter vos propres ForEach méthode générique sur IEnumerable<T>. Voici celle 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, qui ne la chose la plus évidente.)

Il sera intéressant de voir si cela fait partie de .NET 4.0. Il va à l'encontre de la fonctionnelle de style 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());

91voto

mquander Points 32650

Le idiomatiques façon de le faire avec LINQ est de traiter la collecte et le retour d'une nouvelle collection mappé dans la mode que vous voulez. Par exemple, pour ajouter une constante à chaque élément, vous voulez quelque chose comme

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

Faire cela d'une manière fonctionnelle à la place de la mutation de l'état de votre collection existante, souvent vous aide à délimiter les différentes opérations d'une manière qui est à la fois plus facile à lire et plus facile pour le compilateur de raisonner sur.

Si vous êtes dans une situation où vous voulez appliquer une action à chaque élément d'une collection (une action avec des effets secondaires qui sont sans rapport avec le contenu réel de la collection) qui n'est pas vraiment ce que LINQ est le mieux adapté pour, bien que l'on pouvait faire semblant avec Select (ou écrire votre propre IEnumerable méthode d'extension, comme beaucoup de gens ont.) Il est probablement préférable de s'en tenir à un foreach boucle dans ce cas.

42voto

Jaans Points 1003

Vous pouvez également envisager d’aller en parallèle, en particulier si vous ne vous souciez pas de la séquence et que vous voulez 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.

31voto

andy Points 2411

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.

2voto

Drahcir Points 2829

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X