Opérations sur les vecteurs en c# en utilisant l’expression Lambda -2-

Opérations sur les vecteurs en c#  en utilisant l’expression Lambda

Par Ettougourti Mohamed Ali

Nous pouvons aller encore plus loin dans notre exploitation du nouvel outil de programmation que le c# nous offre à savoir l’expression lambda.

(voir article précédent).

L’on peut par exemple ajouter une valeur unique aux différentes valeurs d’un vecteur

x = x.Select(b => b += 0.3).ToArray();

Ou en soustraire une valeur donnée

x = x.Select(b => b -= 0.3).ToArray();

Vous l’avez deviné toutes les opérations arithmétiques sont possibles :

La multiplication:

x = x.Select(b => b *= 0.3).ToArray();

La division:

x = x.Select(b => b /= 0.3).ToArray();

Les précautions d’usage restent de mise pour la division par zéro qui nous donne « infinity » comme résultat.

Les valeurs absolues:

x = x.Select(b => Math.Abs(b)).ToArray();

l’élevation à puissance :

x2 = k2.Select(b => Math.Pow(b, 2)).ToArray();

Pour élever les valeurs de k2, un tableau de type int, à la puissance de 2 nous avons toutefois utilisé un tableau de type double x2 en tant que tableau de destination : Math.pow renvoie en effet une valeur double.

Ces précautions d’usage prises en compte il est possible avec l’expression Lambda d’effectuer toutes les opérations mathématiques sur un vecteur une seule fois et sans recourir à des boucles d’itération.

L’appétit vient en mangeant rien ne peut plus désormais freiner notre élan et l’on est en droit de se demander si d’autres opérations plus fines ne puissent être menées à bien sur des vecteurs.

Le c#  nous offre en matière de tableaux plusieurs instructions de nature à nous faciliter encore plus la tâche.

Ainsi il est possible d’éliminer les doublons d’un vecteur.

Pour ce faire on utilise la fonction ou la méthode « distinct ».

Si l’on initialise un tableau d’entiers avec plusieurs doublons exemple :

int[]k={2,1,2,3,5,3,4,1,6,7,8,2,1,0,8} ;

et si l’on fait appel à distinct() l’on verra qu’une seule valeur des doublons 2,3, 8 ,etc. est retenue et le tableau de rétrécir de 15 éléments à tout juste neuf éléments.

k2 = {2,1,3,5,4,6,7,8,0} ;

Je vois venir votre objection : dans distinct il n’y a pas de signe lambda qui vaille, pourquoi l’invoquer ?

Vous avez raison.  C’est pourquoi je me rattrape sur une autre méthode fort utile qui exige cette fois l’emploi de l’expression lambda.

La méthode sert à trier le tableau par ordre ascendant:

k2 = k2.OrderBy (b=>b).ToArray ();

En inspectant le tableau k2 l’on constate que le zéro initié à la fin du tableau prend désormais la première place et que toutes les valeurs sont bien ordonnées du plus petit au plus grand.

k2 = {0,2,1,3,5,4,6,7,8} ;

Vous ne voulez pas d’un ordre ascendant ?  La même expression lambda nous permet de trier le tableau dans l’ordre descendant du plus grand au plus petit

k2 = k2.OrderByDescending (b => b).ToArray();

Et le tour est joué:

k2 = {8,7,6,5,4,3,2,1,0} ;

Pour faire compliqué alors qu’on peut faire simple on peut évidemment ordonner les valeurs d’un tableau par ordre décroissant ou ascendant puis simplement inverser le tableau grâce à la fonction ou la méthode reverse.

k2.Reverse();

Mais comme vous le constatez l’expression lambda ne figure pas dans l’instruction reverse.

Si vous tenez à employer l’expression lambda dans reverse vous serez vite remis à l’ordre par le compilateur une erreur survient de type « cannot convert lambda expression to type array because it is not a delegate type ».

Ceci n’est pas très clair mais en gros le compilateur refuse d’y aller : ses désirs, comme chacun sait, sont des ordres.

Le plus intéressant reste évidemment de pouvoir travailler sur plusieurs vecteurs.

Pour ce faire nous allons initier un deuxième vecteur baptisé x2 de type double avec des valeurs aléatoire grâce au générateur de nombre aléatoires t précédemment créé.

double[] x2 = new double[100];

x2 = x2.Select(b => b = t.NextDouble()).ToArray();

Pour additionner les valeurs des deux vecteurs nous retrouvons donc notre variable d’itération, next ou index ou de  tout autre nom fantaisiste.(voir article précédent)

Si nous choisissons le vecteur x2 comme vecteur de destination la ligne de code doit s’écrire comme suit :

x2 = x.Select((b,next) => b + x2.ElementAt(next)).ToArray ();

Remarquez que nous pouvons référencer l’élément dans x2 directement à l’aide de deux accolades en reprenant le code sous cette forme:

x2 = x.Select((b, next) => b + x2[next]).ToArray();

C’est aussi avec la même insolite facilité que nous pourrons soustraire un vecteur d’un autre, multiplier deux vecteurs ou diviser l’un par l’autre.

x2 = x.Select((b, next) => b – x2[next]).ToArray();

x2 = x.Select((b, next) => b * x2[next]).ToArray();

x2 = x.Select((b, next) => b / x2[next]).ToArray();

il est tout aussi possible d’effectuer des opérations sur plusieurs tableaux:

x2 = x.Select((b, next) => b + x2[next]* k2[next]).ToArray();

Vous avez testé cette dernière ligne de code et vous avez constaté que ça ne marche pas ?

Autant  pour moi, j’ai oublié de vous parler d’ un détail important:  les tableaux doivent être de même taille d’où l’exception soulevée par le programme : « out of range » ou limites du tableau atteintes.

(103)