Bonjour,
Dans cet exemple, je vous propose une implémentation des méthodes map, reduce, filter que l'on retrouve dans d'autres langages (essentiellement fonctionnels).
Pré-requis vous devez avoir au minimum Delphi 10.3 (Rio). En effet, j'ai développé cet exemple avec Delphi 11 et j'ai utilisé les génériques (disponibles à partir de Delphi 2009) et les variables inline et l'inférence de type (disponibles à partir de Delphi 10.3 il me semble).
Le projet exemple fourni est réalisé avec FMX mais l'unité GBEArray.pas peut être utilisée en VCL également.
Explications
Très brièvement, je vais détailler les rôles de ces 3 méthodes.
La méthode map permet à partir d'un tableau et d'une fonction anonyme passée en paramètre, de créer un nouveau tableau de la même taille que le tableau d'origine mais en appliquant la fonction anonyme à tous les éléments du tableau. La méthode map est souvent comparée à une boucle for.
La méthode filter permet à partir d'un tableau et d'une fonction anonyme passée en paramètre, de créer un nouveau tableau de taille inférieure ou égale au tableau d'origine. La méthode anonyme passée en paramètre permet de filtrer et de ne conserver que les éléments souhaités du tableau d'origine. Le nouveau tableau résultant est donc très souvent de taille plus petite que le tableau d'origine. C'est l'objectif du filtre.
La méthode reduce permet à partir d'un tableau et d'une fonction anonyme passée en paramètre, de créer un unique élément (donc pas un tableau) qui agrège des informations du tableau d'origine à l'aide de la fonction anonyme passée en paramètre.
Exemple
Si vous n'êtes pas familier des langages fonctionnels (comme moi), vous pouvez vous demander quel est l'intérêt de ces méthodes. Nous allons voir cela dans le projet exemple joint à ce post.
Dans le projet joint, vous trouverez l'unité GBEArray.pas qui contient l'implémentation de ces méthodes plus deux autres Sort et Print.
Un petit mot sur ces deux méthodes. Comme je manipule des objets de type TArray, il pouvait être utile d'utiliser leur méthode "sort" pour trier le tableau : d'où 'ajout de la méthode sort au TGBEArray. La méthode Print sert à afficher (à l'aide d'une fonction anonyme passée en paramètre) tous les éléments du tableau. Elle m'a servit au debug et je l'ai laissée.
Le programme exemple fourni lui aussi dans le zip se présente de la manière suivante :
Le bouton "Initialiser" permet d'initialiser une liste aléatoire de 20 entiers affichés dans la liste de gauche. Cela permet d'initialiser un tableau d'entier pour tester les méthodes map, reduce et filter.
Le bouton "Map (x2)" permet de lancer l'exécution de la méthode map sur ce tableau en passant en paramètre la fonction anonyme :
qui va permettre de multiplier par 2 chaque élément du tableau. Le résultat est est un nouveau tableau affiché dans la listbox2 (celle de droite).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 function(value: integer): integer begin result := value * 2; end
Le bouton "Filter (>20)" permet de lancer l'exécution de la méthode filter sur le tableau d'origine en passant en paramètre une fonction anonyme qui indiquera qu'il ne faut conserver que les éléments dont la valeur est > 20.
Le bouton "Reduce (valeur init 0)" permet de lancer l'exécution de la méthode reduce sur le tableau d'origine en passant en paramètre une fonction anonyme qui permettra d'additionner les valeurs des différents éléments du tableau. La valeur initiale est un second paramètre de la méthode reduce qui permet de préciser une valeur initiale au calcul (dans notre cas 0 car on souhaite calculer la somme de tous les entiers du tableau).
Le bouton "Tri" permet de lancer l'exécution de la méthode sort sur le tableau d'origine ce qui produira un nouveau tableau avec les éléments du tableau d'origine trié. A noter, il est possible de passer un TComparer pour spécifier le tri que l'on souhaite faire sur des tableau de types plus complexes qu'un tableau d'entier (voir après)
Là où ça devient intéressant, c'est que les méthodes map, reduce, filter, sort et print peuvent s'enchainer indéfiniment... Le bouton "Map x2, Filter >100 puis Reduce" montre cela car il enchaine :
- un appel à map en multipliant les valeurs par 2
- puis, un appel à filter pour ne conserver que les éléments dont la valeur obtenue est > 100
- puis un appel à reduce pour calculer la somme des valeurs obtenues
Enfin, le bouton "Exemple sur objets" est un exemple avec un tableau d'objet complexe (TPersonne fourni dans l'unité uPersonne.pas). Je crée un jeu d'essai dynamiquement de 10 personnes, puis j'utilise la méthode print pour simplement afficher ce jeu d'essai dans la liste 1, puis appel à filter pour ne sélectionner que les personnes dont le genre est renseigné, puis appel à map pour affecter à ces personnes un nombre de points aléatoire, puis appel à sort (avec utilsation d'un TComparer) pour trier le tableau obtenu par ordre décroissant des points, puis print pour afficher le résultat dans la liste 2 et enfin appel à reduce pour calculer le nombre de points total attribué.
Voici le résultat :
Voici le zip du projet : MapReduce.zip
Partager