IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Codes sources à télécharger Delphi Discussion :

[FMX] Implémentation de MapReduce


Sujet :

Codes sources à télécharger Delphi

  1. #1
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 615
    Points : 3 275
    Points
    3 275
    Billets dans le blog
    2
    Par défaut [FMX] Implémentation de MapReduce
    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 :
    Nom : mapreduce1.png
Affichages : 140
Taille : 14,0 Ko

    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 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function(value: integer): integer
    begin
       result := value * 2;
    end
    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).

    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 :
    Nom : mapreduce2.png
Affichages : 136
Taille : 26,5 Ko

    Voici le zip du projet : MapReduce.zip
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    novembre 2002
    Messages
    8 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 8 450
    Points : 27 382
    Points
    27 382
    Par défaut
    Hello, deux petites remarques sur ton code

    1) les réallocations

    dans initialiserList2 tu utilises "monTableau := monTableau + [StrToInt(s)];" c'est fonctionnel, mais cela implique à chaque itération une réallocation de monTableau pour avoir un élément de plus...selon le gestionnaire mémoire en place ça ne sera pas systématique (allocation d'une zone plus grande que demandée selon le gestionnaire), mais ce n'est pas optimal.

    il est préférable de préallouer le tableau quand on en connait la taille car l'allocation mémoire est un process couteux en temps de calcul
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    procedure TForm2.initialiserList2;
    begin
      ListBox2.Clear;
      SetLength(monTableau, ListBox1.Items.Count); // une seule allocation mémoire
      for var i := 0 to in ListBox1.Items.Count - 1 do
        monTableau[i] := StrToInt(ListBox1.Items[i]);
    end;
    même remarque pour l'unité GBEArray; pour Filter il est préférable d'allouer un premier tableau de la taille de Data puis de le réduire à la taille réellement utile...dans le pire des cas on aura une grosse allocation pour rien, mais ça restera 2 allocations, alors que par iteration sur un très gros tableau tu auras tout un tas d'allocation mémoire.

    2) petit détail, mais dans la méthode Print tu retournes un nouveau TGBEArray<T> alors que tu pourrais retourner Self...au final ça ne change pas grand chose vu Delphi va faire la copie lui même puisqu'on est sur des Record et pas des Objets...mais dans l'idée, on est supposé retourner Self car Data n'est pas modifié
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 615
    Points : 3 275
    Points
    3 275
    Billets dans le blog
    2
    Par défaut
    Bien vu Paul

    Voici la version corrigée : MapReduce_v2.zip

    Pour la fonction Print, à l'origine c'était un copier/coller de la fonction map qui ne devait pas rester mais je la trouve finalement pratique.
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  4. #4
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 615
    Points : 3 275
    Points
    3 275
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Voici une V3 du projet : MapReduce_v3.zip

    Cette version apporte de nouvelles méthodes au TGBEArray :
    - any : elle prend une fonction anonyme en paramètre. Son objectif et de renvoyer un boolean indiquant s'il y a au moins un élément du tableau qui correspond au(x) critère(s) défini(s) dans la fonction anonyme);
    - concat : elle prend un autre TGBEArray<T> en paramètre et permet de concaténer son contenu au TGBEArray d'origine;
    - gather : elle prend une fonction anonyme en paramètre et une chaine de caractères (qui servira de séparateur). Son objectif est de générer un nouveau TGBEArray<string> qui permet de définir des couples clés/valeurs et qui regroupe les clés identiques afin qu'il n'y ait plus de doublon sur ces clés. Les valeurs peuvent alors être la concaténation des valeurs des clés identiques, leurs sommes... C'est la fonction anonyme qui indiquera le traitement à effectuer.

    J'ai mis à jour l'application exemple en ajoutant des exemples pour ces nouvelles fonctionnalités :
    Nom : mapreduce3.png
Affichages : 85
Taille : 22,8 Ko

    Les boutons sont regroupés dans des cadres colorés.
    Le cadre bleu contient les boutons pour lancer les actions sur un tableau de valeurs entières généré aléatoirement. Il faut cliquer sur le bouton Initialiser pour générer ce jeu de données. Le jeu de données sera généré dans la listbox1. Les autres boutons du cadre bleu prendront ce jeu de données pour réaliser leurs actions. Les résultats des traitements seront affichés dans listbox2.
    Le cadre violet est un essai avec un tableau d'un type plus complexe TPersonne. En cliquant sur le bouton correspondant, un jeu de données sera aussi générés dans listbox1 et le résultat des traitements sera affiché dans listbox2.
    Enfin, le cadre jaune contient un TMemo contenant un texte exemple mais il est possible de l'éditer à sa convenance. Le clic sur le bouton de ce cadre va déclencher un traitement qui va lister les mots composants le texte du TMemo et pour chaque mot, compter le nombre d'occurrences de celui ci dans le texte. Un tri est effectué en fin de traitement afin de trier le résultat par ordre alphabétique des mots. Le résultat est affiché dans la listbox2.

    Cela permet de voir de nouveaux exemples sur les possibilités de TGBEArray.
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  5. #5
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 615
    Points : 3 275
    Points
    3 275
    Billets dans le blog
    2
    Par défaut
    Pour information, j'ai mis le projet MapReduce sur mon GitHub : https://github.com/gbegreg/MapReduce
    Il y a déjà une petite évolution suite à une remarque : les méthodes map et reduce peuvent maintenant avoir des types d'entrée et de sortie différents.

    Les futures évolutions de ce projet seront faites sur le GitHub
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique
    Inscrit en
    janvier 2007
    Messages
    13 687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2007
    Messages : 13 687
    Points : 36 861
    Points
    36 861
    Billets dans le blog
    55
    Par défaut
    Bonjour,
    en fait ce n'est pas pour critiquer le projet, mais le titre que j'émets cette note.

    MapReduce, tu m'as tellement habitué à la 3D qu'au départ je n'ai même pas regardé que le code n'était pas sur un dessin de carte que je cochai lu sans même regarder !

    puis-je suggérer quelque chose de plus explicite comme : 'Ajout des fonctions map, reduce et filter à un tableau'
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) ,D11 (Alexandria)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  7. #7
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 615
    Points : 3 275
    Points
    3 275
    Billets dans le blog
    2
    Par défaut
    Bonjour Serge,

    Ça change un peu, il n'y a pas que la 3D

    Par contre, il y aura certainement bientôt un nouveau petit sujet sur la 3D...
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/05/2019, 16h49
  2. Réponses: 22
    Dernier message: 16/09/2016, 18h01
  3. Réponses: 2
    Dernier message: 06/07/2002, 12h36
  4. Implémentation des fonctions mathématiques
    Par mat.M dans le forum Mathématiques
    Réponses: 9
    Dernier message: 17/06/2002, 16h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo