.\" Automatically generated by Pod::Man 2.06 (Pod::Simple 3.04) .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "PERLLOL 1" .TH PERLLOL 1 "2006-03-03" "DocFr" "User Contributed Perl Documentation" .SH "NAME/NOM" .IX Header "NAME/NOM" perllol \- Manipulation des tableaux de tableaux en Perl .SH "DESCRIPTION" .IX Header "DESCRIPTION" .Sh "De\*'claration et acce\*`s aux tableaux de tableaux" .IX Subsection "De'claration et acce`s aux tableaux de tableaux" La chose la plus simple a\*` construire est un tableau de tableaux (parfois appele\*' de fac\*,on peu pre\*'cise une liste de listes). C'est raisonnablement facile a\*` comprendre et presque tout ce qui s'y applique pourra aussi e\*^tre applique\*' par la suite aux structures de donne\*'es plus fantaisistes. .PP Un tableau de tableau est juste un bon vieux tableau \f(CW@TdT\fR auquel vous pouvez acce\*'der avec deux indices, comme \f(CW$TdT[3][2]\fR. Voici une de\*'claration du tableau\ : .PP .Vb 6 \& # affecte a\*` notre tableau un tableau de re\*'fe\*'rences a\*` des tableaux \& @TdT = ( \& [ "fred", "barney" ], \& [ "george", "jane", "elroy" ], \& [ "homer", "marge", "bart" ], \& ); \& \& print $TdT[2][2]; \& bart .Ve .PP Maintenant, vous devez faire bien attention au fait que les parenthe\*`ses exte\*'rieures sont bien des parenthe\*`ses et pas des accolades ou des crochets. C'est parce que vous affectez dans un \f(CW@tableau\fR. Vous avez donc besoin de parenthe\*`ses. Si vous \fIn'\fRaviez \fIpas\fR voulu que cela soit un \f(CW@TdT\fR, mais pluto\*^t une re\*'fe\*'rence a\*` lui, vous auriez pu faire quelque chose du style de ceci\ : .PP .Vb 6 \& # affecte une re\*'fe\*'rence a\*` une liste de re\*'fe\*'rences de liste \& $ref_to_TdT = [ \& [ "fred", "barney", "pebbles", "bambam", "dino", ], \& [ "homer", "bart", "marge", "maggie", ], \& [ "george", "jane", "elroy", "judy", ], \& ]; \& \& print $ref_to_TdT\->[2][2]; .Ve .PP Notez que le type des parenthe\*`ses exte\*'rieures a change\*' et donc notre syntaxe d'acce\*`s aussi. C'est parce que, contrairement au C, en Perl vous ne pouvez pas librement e\*'changer les tableaux et leurs re\*'fe\*'rences. \f(CW$ref_to_TdT\fR est une re\*'fe\*'rence a\*` un tableau, tandis que \f(CW@TdT\fR est un tableau proprement dit. De la me\*^me manie\*`re, \f(CW$TdT[2]\fR n'est pas un tableau, mais une re\*'fe\*'rence a\*` un tableau. Ainsi donc vous pouvez e\*'crire ceci\ : .PP .Vb 2 \& $TdT[2][2] \& $ref_to_TdT\->[2][2] .Ve .PP au lieu de devoir e\*'crire ceci : .PP .Vb 2 \& $TdT[2]\->[2] \& $ref_to_TdT\->[2]\->[2] .Ve .PP Vous pouvez le faire car la re\*`gle dit que, entre des crochets ou des accolades adjacents, vous e\*^tes libre d'omettre la fle\*`che de de\*'re\*'fe\*'rencement. Mais vous ne pouvez pas faire cela pour la toute premie\*`re fle\*`che si c'est un scalaire contenant une re\*'fe\*'rence, ce qui signifie que \f(CW$ref_to_TdT\fR en a toujours besoin. .Sh "De\*'velopper la vo\*^tre" .IX Subsection "De'velopper la vo^tre" Tout ceci est bel et bien pour la de\*'claration d'une structure de donne\*'es fixe, mais si vous voulez ajouter de nouveaux e\*'le\*'ments a\*` la vole\*'e, ou tout contruire a\*` partir de ze\*'ro\ ? .PP Tout d'abord, e\*'tudions sa lecture a\*` partir d'un fichier. C'est quelque chose comme ajouter une range\*'e a\*` la fois. Nous pre\*'sumerons qu'il existe un fichier tout simple dans lequel chaque ligne est une range\*'e et chaque mot un e\*'le\*'ment. Voici la bonne fac\*,on de le faire si vous essayez de de\*'velopper un tableau \f(CW@TdT\fR les contenant tous\ : .PP .Vb 4 \& while (<>) { \& @tmp = split; \& push @TdT, [ @tmp ]; \& } .Ve .PP Vous auriez aussi pu charger tout cela dans une fonction\ : .PP .Vb 3 \& for $i ( 1 .. 10 ) { \& $TdT[$i] = [ somefunc($i) ]; \& } .Ve .PP Ou vous auriez pu avoir une variable temporaire trai\*^nant dans le coin et contenant le tableau. .PP .Vb 4 \& for $i ( 1 .. 10 ) { \& @tmp = somefunc($i); \& $TdT[$i] = [ @tmp ]; \& } .Ve .PP Il est tre\*`s important que vous vous assuriez d'utiliser le constructeur de re\*'fe\*'rence de tableau \f(CW\*(C`[]\*(C'\fR. C'est parce que ceci serait tre\*`s mauvais\ : .PP .Vb 1 \& $TdT[$i] = @tmp; .Ve .PP Voyez vous, affecter comme ceci un tableau nomme\*' a\*` un scalaire ne fait que compter le nombre d'e\*'le\*'ments dans \f(CW@tmp\fR, ce qui n'est probablement pas ce que vous de\*'sirez. .PP Si vous utilisez \f(CW\*(C`use strict\*(C'\fR, vous devrez ajouter quelques de\*'clarations pour que tout fonctionne\ : .PP .Vb 6 \& use strict; \& my(@TdT, @tmp); \& while (<>) { \& @tmp = split; \& push @TdT, [ @tmp ]; \& } .Ve .PP Bien su\*^r, vous n'avez pas du tout besoin de donner un nom au tableau temporaire\ : .PP .Vb 3 \& while (<>) { \& push @TdT, [ split ]; \& } .Ve .PP Vous n'e\*^tes pas non plus oblige\*' d'utiliser \fIpush()\fR. Vous pourriez juste faire une affectation directe si vous savez ou\*` vous voulez le mettre\ : .PP .Vb 5 \& my (@TdT, $i, $line); \& for $i ( 0 .. 10 ) { \& $line = <>; \& $TdT[$i] = [ split ' ', $line ]; \& } .Ve .PP ou me\*^me juste\ : .PP .Vb 4 \& my (@TdT, $i); \& for $i ( 0 .. 10 ) { \& $TdT[$i] = [ split ' ', <> ]; \& } .Ve .PP Vous devriez en ge\*'ne\*'ral lorgner d'un regard mauvais l'usage de fonctions qui peuvent potentiellement retourner des listes dans un contexte scalaire sans le formuler explicitement. Ceci sera plus clair pour le lecteur de passage\ : .PP .Vb 4 \& my (@TdT, $i); \& for $i ( 0 .. 10 ) { \& $TdT[$i] = [ split ' ', scalar(<>) ]; \& } .Ve .PP Si vous voulez utiliser une variable \f(CW$ref_to_TdT\fR comme re\*'fe\*'rence a\*` un tableau, vous devez faire quelque chose comme ceci\ : .PP .Vb 3 \& while (<>) { \& push @$ref_to_TdT, [ split ]; \& } .Ve .PP Maintenant vous pouvez ajouter de nouvelles range\*'es. Et pour ajouter de nouvelles colonnes\ ? Si vous traitez juste des matrices, le plus facile est souvent d'utiliser une simple affectation\ : .PP .Vb 5 \& for $x (1 .. 10) { \& for $y (1 .. 10) { \& $TdT[$x][$y] = func($x, $y); \& } \& } \& \& for $x ( 3, 7, 9 ) { \& $TdT[$x][20] += func2($x); \& } .Ve .PP Peu importe que ces e\*'le\*'ments soient de\*'ja\*` la\*` ou pas\ : ils seront cre\*'e\*'s joyeusement pour vous et, si besoin, les e\*'le\*'ments interme\*'diaires seront initialise\*'s a\*` \f(CW\*(C`undef\*(C'\fR. .PP Si vous voulez juste en ajouter a\*` une range\*'e, vous devrez faire quelque chose ayant l'air un peu plus bizarre\ : .PP .Vb 2 \& # ajoute de nouvelles colonnes a\*` une range\*'e existante \& push @{ $TdT[0] }, "wilma", "betty"; .Ve .PP Remarquez qu'on \fIne pourrait pas\fR juste dire\ : .PP .Vb 1 \& push $TdT[0], "wilma", "betty"; # FAUX ! .Ve .PP En fait, cela ne se compilerait me\*^me pas. Pourquoi donc\ ? Parce que l'argument de \fIpush()\fR doit e\*^tre un ve\*'ritable tableau, et non pas une simple re\*'fe\*'rence. .Sh "Acce\*`s et sortie" .IX Subsection "Acce`s et sortie" Maintenant il est temps de sortir votre structure de donne\*'es. Comment allez-vous faire une telle chose\ ? Eh bien, si vous voulez uniquement l'un des e\*'le\*'ments, c'est trivial\ : .PP .Vb 1 \& print $TdT[0][0]; .Ve .PP Si vous voulez sortir toute la chose, toutefois, vous ne pouvez pas dire\ : .PP .Vb 1 \& print @TdT; # FAUX .Ve .PP car vous obtiendrez juste la liste des re\*'fe\*'rences et perl ne de\*'re\*'fe\*'rencera jamais automatiquement les choses pour vous. Au lieu de cela, vous devez faire tourner une boucle ou deux. Ceci imprime toute la structure, en utilisant la construction \fIfor()\fR dans le style du shell pour boucler d'un bout a\*` l'autre de l'ensemble des indices exte\*'rieurs. .PP .Vb 3 \& for $aref ( @TdT ) { \& print "\et [ @$aref ],\en"; \& } .Ve .PP Si vous voulez garder la trace des indices, vous pouvez faire ceci\ : .PP .Vb 3 \& for $i ( 0 .. $#TdT ) { \& print "\et elt $i is [ @{$TdT[$i]} ],\en"; \& } .Ve .PP ou peut\-e\*^tre me\*^me ceci. Remarquez la boucle inte\*'rieure. .PP .Vb 5 \& for $i ( 0 .. $#TdT ) { \& for $j ( 0 .. $#{$TdT[$i]} ) { \& print "elt $i $j is $TdT[$i][$j]\en"; \& } \& } .Ve .PP Comme vous pouvez le voir, cela devient un peu complique\*'. C'est pourquoi il est parfois plus facile de prendre une variable temporaire en chemin\ : .PP .Vb 6 \& for $i ( 0 .. $#TdT ) { \& $aref = $TdT[$i]; \& for $j ( 0 .. $#{$aref} ) { \& print "elt $i $j is $TdT[$i][$j]\en"; \& } \& } .Ve .PP Hmm... c'est encore un peu laid. Pourquoi pas ceci\ : .PP .Vb 7 \& for $i ( 0 .. $#TdT ) { \& $aref = $TdT[$i]; \& $n = @$aref \- 1; \& for $j ( 0 .. $n ) { \& print "elt $i $j is $TdT[$i][$j]\en"; \& } \& } .Ve .Sh "Tranches" .IX Subsection "Tranches" Si vous voulez acce\*`der a\*` une tranche (une partie d'une range\*'e) d'un tableau multidimensionnel, vous allez devoir faire un peu d'indic\*,age fantaisiste. Car, tandis que nous avons un joli synonyme pour les e\*'le\*'ments seuls via la fle\*`che de pointeur pour le de\*'re\*'fe\*'rencement, il n'existe pas de telle commodite\*' pour les tranches (souvenez\-vous, bien su\*^r, que vous pouvez toujours e\*'crire une boucle pour effectuer une ope\*'ration sur une tranche). .PP Voici comment faire une ope\*'ration en utilisant une boucle. Nous supposerons avoir une variable \f(CW@TdT\fR comme pre\*'ce\*'demment. .PP .Vb 5 \& @part = (); \& $x = 4; \& for ($y = 7; $y < 13; $y++) { \& push @part, $TdT[$x][$y]; \& } .Ve .PP Cette me\*^me boucle peut e\*^tre remplace\*'e par une ope\*'ration de tranche\ : .PP .Vb 1 \& @part = @{ $TdT[4] } [ 7..12 ]; .Ve .PP mais comme vous pouvez l'imaginer, c'est pluto\*^t rude pour le lecteur. .PP Et si vous vouliez une \fItranche a\*` deux dimensions\fR, telle que \f(CW$x\fR varie dans 4..8 et \f(CW$y\fR dans 7 a\*` 12\ ? Hmm... voici la fac\*,on simple\ : .PP .Vb 6 \& @newTdT = (); \& for ($startx = $x = 4; $x <= 8; $x++) { \& for ($starty = $y = 7; $y <= 12; $y++) { \& $newTdT[$x \- $startx][$y \- $starty] = $TdT[$x][$y]; \& } \& } .Ve .PP Nous pouvons re\*'duire une partie du bouclage via des tranches. .PP .Vb 3 \& for ($x = 4; $x <= 8; $x++) { \& push @newTdT, [ @{ $LoL[$x] } [ 7..12 ] ]; \& } .Ve .PP Si vous faisiez des transformations schwartziennes, vous auriez probablement choisi map pour cela\ : .PP .Vb 1 \& @newTdT = map { [ @{ $TdT[$_] } [ 7..12 ] ] } 4 .. 8; .Ve .PP Bien su\*^r, si votre directeur vous accuse de rechercher la se\*'curite\*' de l'emploi (ou l'inse\*'curite\*' rapide) a\*` l'aide d'un code inde\*'chiffrable, il sera difficile d'argumenter. :\-) Si j'e\*'tais vous, je mettrais cela dans une fonction\ : .PP .Vb 5 \& @newTdT = splice_2D( \e@LoL, 4 => 8, 7 => 12 ); \& sub splice_2D { \& my $lrr = shift; # re\*'f a\*` un tableau de re\*'fs. de tableau ! \& my ($x_lo, $x_hi, \& $y_lo, $y_hi) = @_; \& \& return map { \& [ @{ $lrr\->[$_] } [ $y_lo .. $y_hi ] ] \& } $x_lo .. $x_hi; \& } .Ve .SH "VOIR AUSSI" .IX Header "VOIR AUSSI" perldata, perlref, perldsc. .SH "AUTEUR" .IX Header "AUTEUR" Tom Christiansen <\fItchrist@perl.com\fR> .PP Dernie\*`re mise a\*` jour : Thu Jun 4 16:16:23 \s-1MDT\s0 1998 .SH "TRADUCTION" .IX Header "TRADUCTION" .Sh "Version" .IX Subsection "Version" Cette traduction franc\*,aise correspond a\*` la version anglaise distribue\*'e avec perl 5.8.8. Pour en savoir plus concernant ces traductions, consultez . .Sh "Traducteur" .IX Subsection "Traducteur" Roland Trique <\fIroland.trique@free.fr\fR>. .Sh "Relecture" .IX Subsection "Relecture" Re\*'gis Julie\*' <\fIregis.julie@cetelem.fr\fR>. Paul Gaborit (Paul.Gaborit at enstimac.fr).