2009-01-28 10 views
0

Nous savons que si vous avez:Convert extrait existant de code à utiliser Array.ForEach

var aa = new [] { 1, 2, 3, 4, 5 }; 
for (int i = 0; i < aa.length; ++i) 
{ 
    aa[i] = aa[i] + 1; 
} 

il est vraiment

var aa = new [] { 1, 2, 3, 4, 5 }; 
Arrary.ForEach(aa, a => a + 1); 

Cependant, si je devais ceci:

var aa = new [] { 1, 2, 3, 4, 5 }; 
var ab = new [] { 1, 2, 3, 4, 5 }; 
for (int i = 0; i < aa.length; ++i) 
{ 
    aa[i] = ab[i] + 1; 
} 

Puis-je convertir ceci pour n'utiliser qu'un seul Array.ForEach? Ou, comment le feriez-vous, si vous voulez aller fou toute la programmation fonctionnelle? Clunky pour les boucles a juste l'air moche.

+0

Je n'arrive pas à compiler votre premier code ForEach. "new Action (a => a + 1)" n'a pas de sens, puisque "a => a + 1" est une action , et "a + 1" n'est pas une instruction. –

+0

Je suis désolé, je suis au travail maintenant, donc je ne suis pas sur le framework .Net 3.5. Je sais que l'utilisation d'un délégué fonctionnerait bien, je ne suis pas sûr si cela peut être changé pour utiliser une expression lambda à la place ... –

+0

"Ou, comment le feriez-vous, si vous voulez aller toute la programmation fonctionnelle folle?" - Utilisez F # :) – MichaelGG

Répondre

1

Ce ne sera pas rapide, mais il pourrait bien travailler

var aa = new [] { 1, 2, 3, 4, 5 }; 
var ab = new [] { 1, 2, 3, 4, 5 }; 
Array.ForEach(aa, new Action(a => ab[Array.IndexOf(a)] + 1)); 

Malheureusement Thiswill fonctionne pas pour un tableau avec des éléments en double.

+0

Pourquoi ce ne sera pas rapide? –

+0

Parce que Array.IndexOf est une opération O (n) à l'intérieur d'un ForEach qui est également une opération O (n). –

2

Il est pas joli, mais cela fonctionnera (en utilisant la surcharge Select() qui retourne l'index de l'élément):

var aa = new[] { 1, 2, 3, 4, 5 }; 
var ab = new[] { 1, 2, 3, 4, 5 }; 

Array.ForEach(
    aa.Select((x, i) => i).ToArray(), 
    i => aa[i] = ab[i] + 1); 

à mon humble avis un simple « pour » boucles est beaucoup plus facile à comprendre dans ce Cas.

+0

Je ne peux pas trouver la surcharge Select, est-ce une partie de Linq, ou est-ce une méthode écrite sur mesure? –

+0

Ouais juste une partie de Linq. Select peut prendre une fonction qui passe l'index (un int) comme deuxième paramètre. –

2

Une autre approche similaire:

Enumerable.Range(0, ab.Length).Select(i => aa[i] = ab[i] + 1); 
// Will not work if aa.Length != ab.Length 
4

Que diriez-vous:

aa = ab.ConvertAll(x => x+1); 
+0

Ah, ah, il y a plein de façons de le faire si vous êtes en train de le faire! Je pensais qu'il voulait le faire en place. –

+0

Ouais, le faire avec un tableau de destination est "intéressant". Il peut être amusant d'ajouter une méthode d'extension qui ressemble à ConvertAll mais qui prend un tableau de destination existant. –

+0

Bonne réponse btw. Mais en fait j'ai simplement inventé un problème de jouet (pas le vrai que j'essayais de résoudre) où je suis dans une situation où j'avais besoin de l'index pour faire référence à quelques autres tableaux.Mais merci quand même :) –

-1

Pas une réponse directe, mais vous voulez ForEach2, qui effectue une itération sur deux séquences/tableaux. Malheureusement, ceci n'est pas inclus avec la BCL, vous devrez donc l'ajouter.

Mais si vous essayez de faire fonctionner en C#, vous aurez probablement une bibliothèque d'assistance de toute façon, donc ce n'est pas un gros problème.

0
var aa = new[] { 1, 2, 3, 4, 5 }; 
var ab = new[] { 1, 2, 3, 4, 5 }; 

var index = 0; 
Array.ForEach(aa, a => { aa[index] = ab[index] + 1; index++; }); 

Cela ne fonctionnerait-il pas? Son 1 Array.ForEach avec l'indexeur tenu à l'extérieur de la Array.ForEach.