Iterations

Published: March 27, 2016, 1:45 p.m.

b'

\\xc9pisode 10 sur des traitements classiques sur les listes.\\nEn Ruby on appelle \\xe7a Enumerable, mais heureusement les mots\\nsont partag\\xe9s dans la plupart des biblioth\\xe8ques et langages.

\\n\\n

Traitons d\\u2019abord quelques oublis classiques de d\\xe9butants\\n(et d\\u2019\\xe9tourderies d\\u2019experts aussi, ne vous sentez pas ridicules\\nquand \\xe7a vous arrive, c\\u2019est le jeu) sur des listes et \\u201cboucles\\u201d.

\\n\\n

each et les it\\xe9rations

\\n\\n

Imaginez-vous dans un emploi qui traite des dossiers un par un.\\nVotre m\\xe9thode de travail est de prendre des fiches, et les traiter.\\nPartons sur un tableau nomm\\xe9 a et contenant les chiffres de 1 \\xe0 5.\\na = [1,2,3,4,5] # ou (1..5).to_a

\\n\\n

Traiter, \\xe7a peut vouloir dire prendre une feuille, noter quelque\\nchose ailleurs, et les remettre exactement \\xe0 leur place.\\nC\\u2019est ce que fait each : le code b = a.each{|x| x * 2}\\nmet effectivement un tableau dans b, mais [1,2,3,4,5]\\net non pas [2,4,6,8,10].

\\n\\n

map et les pi\\xe8ges s\\xe9mantiques

\\n\\n

Traiter, \\xe7a peut vouloir dire prendre un dossier a,\\nouvrir un nouveau dossier vierge, et mettre dans ce nouveau\\ndossier le r\\xe9sultat de votre travail.

\\n\\n

Le pi\\xe8ge, c\\u2019est qu\\u2019apr\\xe8s vous pouvez tout aussi bien mettre\\nune nouvelle \\xe9tiquette b sur ce nouveau dossier, ou\\nvoler l\\u2019\\xe9tiquette du dossier a pour la coller sur ce\\nnouveau dossier.

\\n\\n

Pire encore, vous pouvez travailler soit avec des photocopies\\nde chacune des feuilles de a, soit modifier physiquement\\nchacune des feuilles : vous avez mis du surligneur, d\\xe9chir\\xe9\\nun coupon, \\xe9crit sur la fiche ou mis un tampon ?\\nImpossible de retrouver la feuille de d\\xe9part dans l\\u2019\\xe9tat de d\\xe9part !

\\n\\n

En terme de code, ces trois options donneraient cela :

\\n\\n

b = a.map {|x| x * 2}, qui renvoie bien [2,4,6,8,10]\\net le stocke dans b, sans aucunement d\\xe9ranger le tableau a.

\\n\\n

a = a.map {|x| x * 2} a travaill\\xe9 sur une copie de a\\n(sans la nommer) puis finit par lui recoller l\\u2019\\xe9tiquette a dessus.\\nOn ne parle pas des informations de d\\xe9part : en ayant redonn\\xe9\\nl\\u2019\\xe9tiquette au nouveau dossier, on n\\u2019a pas vraiment pr\\xe9vu de moyen\\nd\\u2019aller chercher les anciennes informations.

\\n\\n

[\'bonjour\', \'au revoir\'].map{|x| x.upcase!} a vraiment modifi\\xe9\\nle contenu, chacune des cha\\xeenes de caract\\xe8res du tableau.\\nOn note d\\u2019ailleurs que par convention, les Rubyistes mettront un\\npoint d\\u2019exclamation \\xe0 la fin des noms de m\\xe9thodes \\u201cdestructrices\\u201d,\\nc\\u2019est \\xe0 dire qui changent le contenu de d\\xe9part.

\\n\\n
str = "Bonjour" # => "Bonjour"   # valeur de d\\xe9part\\nstr.upcase      # => "BONJOUR"   # \\xe7a n\'est pas la m\\xeame donn\\xe9e\\nstr             # => "Bonjour"   # on n\'a pas touch\\xe9 \\xe0 str\\nstr.upcase!     # => "BONJOUR"   # on a mis en majuscule et on alt\\xe8re str\\nstr             # => "BONJOUR"   # str a \\xe9t\\xe9 modifi\\xe9e\\n
\\n
\\n\\n

Traitement \\u201cen place\\u201d

\\n\\n

Pareillement pour les dossiers, si je veux trier mon dossier a\\nje n\\u2019ai pas forc\\xe9ment envie de pr\\xe9parer un nouveau dossier pour\\nconserver les valeurs tri\\xe9es, et jouer ensuite avec les \\xe9tiquettes.

\\n\\n

Je peux vouloir simplement dire que tout se fait dans le tableau a\\net que je n\\u2019ai pas besoin de faire de copies. \\xc7a s\\u2019appelle un\\ntraitement \\u201cin-place\\u201d et la plupart des rubyistes vont le faire\\navec des m\\xe9thodes finissant par des points d\\u2019exclamation.

\\n\\n

On n\\u2019en voit pas dans Enumerable, mais on voit beaucoup de paires\\ndans la classe Array : sort et sort!, rotate, reverse, uniq\\u2026

\\n\\n

D\\u2019une liste \\xe0 un seul r\\xe9sultat

\\n\\n

Je pense qu\\u2019il faudra un autre \\xe9pisode pour toutes ces super fonctions.\\nEn attendant, il y a une classe enti\\xe8re de besoins \\xe0 voir.

\\n\\n

Imaginez que votre travail c\\u2019est de prendre une liste de fiches,\\net de ressortir un seul nombre : la somme des paiements,\\nou le nombre de mauvais payeurs par exemple.

\\n\\n

Cette m\\xe9thode a trois noms.\\nRuby l\\u2019appelle reduce : on \\u201cr\\xe9duit\\u201d les N fiches \\xe0 1 r\\xe9sultat.

\\n\\n

Ruby l\\u2019appelle aussi inject : on \\u201cinjecte\\u201d la valeur z\\xe9ro,\\npuis on va regarder chaque fiche pour ajouter la somme d\\u2019argent\\nde LA fiche au total \\u201ctemporaire\\u201d et ainsi de suite.\\nPar exemple, 50 + 100 + 25 + 20 + 5 : vous avez probablement fait\\nl\\u2019addition \\xe9tape par \\xe9tape.

\\n\\n
[50, 100, 25, 20, 5].inject(0) {|somme, obj| somme + obj}\\n[100, 25, 20, 5].inject(50) {|somme, obj| somme + obj}\\n[25, 20, 5].inject(150) {|somme, obj| somme + obj}\\n[20, 5].inject(175) {|somme, obj| somme + obj}\\n[5].inject(195) {|somme, obj| somme + obj}\\n# => 200\\n
\\n
\\n\\n

Le troisi\\xe8me nom n\\u2019est pas tr\\xe8s utilis\\xe9 en Ruby, mais dans le reste\\ndes langages : fold. Il applique le r\\xe9sultat \\xe9tape par \\xe9tape, comme\\non vient de voir.\\nJ\\u2019aime bien l\\u2019image que ce mot donne : si vous avez d\\xe9j\\xe0 vu de vieilles\\nimprimantes avec des piles de papier qui se pliaient et d\\xe9pliaient,\\nc\\u2019est vraiment pour moi l\\u2019acte de replier une tr\\xe8s longue liste de\\npages en un accord\\xe9on qui prend moins de place et affiche en bas\\nle r\\xe9sultat voulu.

\\n\\n

That\\u2019s all folks!

\\n\\n

Et bien voil\\xe0, c\\u2019est d\\xe9j\\xe0 assez long pour cette fois !\\nMon but n\\u2019est pas franchement de vous lire la doc Ruby \\xe0\\nvoix haute, donc allez lire\\nEnumerable,\\nArray,\\nHash,\\net aussi String,\\nles op\\xe9rations sur les cha\\xeenes de caract\\xe8res, pour faire bonne mesure,\\nmais peut-\\xeatre que je ferai un \\xe9pisode \\u201crappel\\u201d sur quelques-unes de\\nces m\\xe9thodes un de ces jours.

'