8
votes

Comment puis-je imprimer un tableau de deux dimensions perl?

J'essaie d'écrire un script Perl simple qui lit un * .csv, place les lignes du fichier * .csv dans une matrice bidimensionnelle, imprime un élément hors de la matrice et imprime une rangée de la matrice. .

#!/usr/bin/perl
use strict;
use warnings;

open(CSV, $ARGV[0]) || die("Cannot open the $ARGV[0] file: $!");
my @row;
my @table;

while(<CSV>) {
    @row = split(/\s*,\s*/, $_);
    push(@table, @row);
}
close CSV || die $!;

foreach my $element ( @{ $table[0] } ) {
    print $element, "\n";
}

print "$table[0][1]\n";


3 commentaires

+1 pour ne pas gaspiller le temps de tout le monde en omettant utiliser strict; Utiliser des avertissements; .


Vous devriez vraiment éviter 2 argument Ouvrir . Il possède un certain nombre de problèmes qui sont les meilleurs à éviter (pour la discussion, voir cet article de Perlmonks 2001: perlmonks.org /? node_id = 131085 ) Voir ceci pour info sur les poignées lexicales: Stackoverflow.com/questions/613906/...


Voir Perldoc Perllol - Accéder à l'accès et à l'impression


6 Réponses :


3
votes
a,b,c
d,e,f
g,h,i

0 commentaires

2
votes

Vous avez besoin de deux modifications:

  1. Utilisez une variable locale pour la ligne
  2. Utilisez des références pour le tableau que vous avez mis dans @Table

    Donc, votre programme devrait regarder ceci: xxx


0 commentaires

1
votes

Peut-être que c'est ce que vous voulez réellement:

#!/usr/bin/perl
use strict;
use warnings;

open(CSV, $ARGV[0]) || die("Cannot open the $ARGV[0] file: $!");
my @table;

while(<CSV>) {
        my @row = split(/\s*,\s*/, $_);
        push(@table, \@row);
}
close CSV || die $!;

foreach my $element ( @{ $table[0] } ) {
    print $element, "\n";
}

print "$table[0][1]\n";


1 commentaires

Il serait préférable d'utiliser la forme moderne d'ouverture: ouvert (mon $ CSV, '<', $ argv [0])



0
votes

Changer xxx

puis il imprime ok.


2 commentaires

... Mais la mauvaise chose de @row n'est-elle pas créée à l'intérieur de la boucle.


... mais cela pourrait être réparé si vous dites push @table, [@row] pour utiliser une référence à une copie de @row .



11
votes

Vous ne créez pas une matrice bidimensionnelle (un AOA ou «Tableau de tableaux» dans Perl-Parlance). Cette ligne: xxx

ajoute les données dans @row à @Table . Vous devez appuyer à la place d'une référence et créer une nouvelle variable à chaque fois via la boucle afin de ne pas pousser la même référence à plusieurs reprises: xxx

tout en utilisant Split est correct pour les fichiers CSV triviaux, il est malheureusement insuffisant pour autre chose. Utilisez un module comme texte :: csv_xs à la place: xxx


2 commentaires

TRAY-OF-TRAY est la bonne nomenclature. Il n'y a vraiment pas de liste de liste à Perl. (Nom du Perllol Manpage Nonobstant. Soupir.)


@friedo: point pris. J'ai vu lol utilisé plusieurs fois, mais ce n'est pas une excuse pour diffuser des idées fausses. Fixé.



2
votes

Si vous appelez PUSH avec les arguments de la liste, vous appendez la première liste avec la liste restante dans la mode Stack Wise. Lisez à propos de la poussée à Perldoc . Donc votre appel de pousser (@Table, @row); code> crée une liste plus longue @Table code>, pas un tableau à deux dimensions.

Vous avez reçu plusieurs messages qui Appuyez sur une référence de liste à @row code> comme \ @ ligne code> créera une liste de lignes, et cela fonctionne en effet. J'ai tendance à le faire un peu différemment. Bien sûr, avec Perl, il y a toujours une autre façon de le faire! P>

syntaxiquement, vous pouvez également appuyer sur une référence de matrice anonyme dans l'élément scalaire d'une liste pour créer une liste multidimensionnelle. La chose la plus importante à savoir sur les références à Perl est la suivante: 1) Ils sont un scalaire et 2) ils peuvent faire référence à tout ce qui est dans Perl - Code, tableau, hachage, une autre référence. Passez un peu de temps avec le Tutoriel Perl Ref et cela deviendra plus clair. Avec votre code, il suffit d'ajouter [] code> autour de l'élément que vous souhaitez être la 2e dimension de votre liste, donc push (@Table, @row); code> devrait être Appuyez sur (@Table, [@row]); code> dans le même sens, vous mettez [] code> autour de votre scission afin qu'il devienne poussoir (@ split ( / \ s *, \ s * /, $ _)]]); code> Cela effectuera simultanément la scission et créera une matrice anonyme au résultat. P>

Le problème spécifique que vous avez, comment Pour créer et accéder à une liste multidimensionnelle, est également très bien traitée dans Tom Christensen's Tutoriel de Perllol le Des solutions à vos problèmes spécifiques avec votre code sont directement traitées ici. P>

Réécrivez votre code avec le code exact de Tom's Exemple en Perllol, il devient: P>

#!/usr/bin/perl
use strict;
use warnings;

my (@row, @table, $n, $rowref);

while(<DATA>) {
        chomp;
        # regex to separate CSV (use of a cpan module for CSV STRONGLY advised...
        @row = /(?:^|,)("(?:[^"]+|"")*"|[^,]*)/g;
        for (@row) {
            if (s/^"//) { s/"$//; s/""/"/g; }
        }
        push(@table, [ @row ]); #Note the [ ] around the list
}

# Now the table is created, print it:
my $rowcnt=0;
foreach $rowref (@table) {
    print "row $rowcnt:\n";
    $rowcnt++;
    print "  [ @$rowref ], \n";
}   

# You can access the table in the classic [i][j] form:
for my $i ( 0 .. $#table ) {
    $rowref = $table[$i];
    $n = @$rowref - 1;
    for my $j ( 0 .. $n ) {
        print "element $i, $j of table is $table[$i][$j]\n";
    }
}

# You can format it:
for my $i ( 0 .. $#table ) {
    print "$table[$i][0] $table[$i][1]\n";
    print "$table[$i][2]\n";
    print "$table[$i][3], $table[$i][4] $table[$i][5]\n\n";
}


__DATA__
Mac,Doe,120 jefferson st.,Riverside, NJ, 08075
Jack,McGinnis,220 hobo Av.,Phila, PA,09119
"John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075
Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234
,Blankman,,SomeTown, SD, 00298
"Joan ""Joan, the bone""",Jett,"9th, at Terrace plc",Desert City,CO,00123


0 commentaires