2010-10-14 9 views
2

J'essaie actuellement de passer un fichier matriciel de 32 par 48 à un tableau multi-dimensionnel en Perl. Je suis en mesure d'accéder à toutes les valeurs mais j'ai des problèmes d'accès à une valeur spécifique. Toute aide serait grandement appréciée. J'ai mis un lien vers l'ensemble de données ainsi que le code que j'ai ci-dessous.Comment créer un tableau bidimensionnel en Perl?

Voici un lien vers l'ensemble de données: http://paste-it.net/public/x1d5301/

Voici ce que j'ai pour le code en ce moment.

#!/usr/bin/perl 

open FILE, "testset.txt" or die $!; 
my @lines = <FILE>; 

my $size = scalar @lines; 

my @matrix = (1 .. 32); 
my $i = 0; 
my $j = 0; 
my @micro; 

foreach ($matrix) 
{ 

foreach ($lines) 
{ 
    push @{ $micro[$matrix]}, $lines; 
} 
} 
+1

lol pour 'utiliser l'anglais; ' – Zaid

+0

il suffit de poser la question et couper tout le reste. –

+0

@Zaid J'ai supprimé l'utilisation – Alos

Répondre

7

Il ne semble pas que vous comprenez que $matrix indique @matrix quand il est immédiatement suivi d'un indexeur de tableau: [ $slot ]. Sinon, $matrix est une variable complètement différente de @matrix (et les deux également différent de %matrix). Voir perldata.

#!/usr/bin/perl 
use English; 

Ne le faites pas! utiliser l'anglais-- de cette façon!

Cela apporte $MATCH, $PREMATCH et $POSTMATCH et incurrs la $& redoutée, `$, pénalité $'. Vous devriez attendre jusqu'à ce que vous soyez en utilisant une variable anglaise, puis importez juste cela.

open FILE, "testset.txt" or die $!; 

Deux choses: 1) utiliser lexical file handles et 2) Les trois arg open.

my @lines = <FILE>; 

Tant que je choisis: Ne pas slurp gros fichiers. (Pas le cas ici, mais il est un bon avertissement.)

my $size = scalar @lines; 

my @matrix = (1 .. 32); 
my $i = 0; 
my $j = 0; 
my @micro; 

Je vois que nous sommes au stade ici ...

foreach ($matrix) { 

Vous ne disposez pas d'une variable que vous avez $matrix une variable @matrix.

foreach ($lines) { 

La même chose est vraie avec $lines.

 push @{ $micro[$matrix]}, $lines; 
    } 
} 

Rewrite:

use strict; 
use warnings; 
use English qw<$OS_ERROR>; # $! 
open(my $input, '<', 'testset.txt') or die $OS_ERROR; 

# I'm going to assume space-delimited, since you don't show 
my @matrix; 
# while (defined($_ = <$input>))... 
while (<$input>) { 
    chomp; # strip off the record separator 
    # load each slot of @matrix with a reference to an array filled with 
    # the line split by spaces. 
    push @matrix, [ split ]; # split = split(' ', $_) 
} 
+0

@Axeman FYI: 'split' sans arguments est' split '' 'non' split/\ s +/' –

+0

@Sinan: Pas sur redhat Perl 5.8.7 ou Strawberry Perl 5.12.1: perl-MSmart :: Commentaires $ _ = '1 2 3 4 5'; mon @a = split; ### @a ### @a: [ ### '1', '2 ###', ### ' 3', ### '4', ## # '5' ###] – Axeman

+1

@Sinan, bien HTML a compressé les espaces, mais il y a toutes sortes d'espaces et d'onglets là-dedans. :/ – Axeman

2

Vous devez probablement chomp les valeurs:

chomp(my @lines = <FILE>); 
1

Je fais cette CW parce que son seul but est de clarifier un point tangent j'ai fait dans mon commentaire à @Axeman's answer. Voir perldoc -f split:

Une scission sur /\s+/ est comme un split(' ') sauf que les espaces blancs menant produit un premier champ vide.Une scission sans arguments fait vraiment split(' ', $_) en interne.

#!/usr/bin/perl 

use YAML; 

$_ = "\t1 2\n3\f4\r5\n"; 

print Dump { 'split'  => [ split  ] }, 
      { "split ' '" => [ split ' ' ] }, 
      { 'split /\s+/' => [ split /\s+/ ] } 
      ; 

Sortie:

--- 
split: 
    - 1 
    - 2 
    - 3 
    - 4 
    - 5 
--- 
split ' ': 
    - 1 
    - 2 
    - 3 
    - 4 
    - 5 
--- 
split /\s+/: 
    - '' 
    - 1 
    - 2 
    - 3 
    - 4 
    - 5
3

Si vous allez faire un peu de mathématiques, vous pourriez envisager PDL (la langue des données Perl). Vous pouvez facilement configurer votre matrice et avant les opérations sur elle:

use 5.010; 

use PDL; 
use PDL::Matrix; 

my @rows; 
while(<DATA>) { 
    chomp; 
    my @row = split /\s+/; 
    push @rows, \@row; 
    } 

my $a = PDL::Matrix->pdl(\@rows); 
say "Start ", $a; 

$a->index2d(1, 2) .= 999; 
say "(1,2) to 999 ", $a; 

$a++; 
say "Increment all ", $a; 

__DATA__ 
1 2 3 
4 5 6 
7 8 9 
2 3 4 

La sortie montre l'évolution de la matrice:

Start 
[ 
[1 2 3] 
[4 5 6] 
[7 8 9] 
[2 3 4] 
] 

(1,2) to 999 
[ 
[ 1 2 3] 
[ 4 5 999] 
[ 7 8 9] 
[ 2 3 4] 
] 

Increment all 
[ 
[ 2 3 4] 
[ 5 6 1000] 
[ 8 9 10] 
[ 3 4 5] 
] 

Il y a un peu de puissance pour exécuter des opérations arbitraires et complexes sur tous les membres de la matrice comme j'ai ajouté 1 à chaque membre. Vous sautez complètement les acrobaties en boucle.

En plus de cela, PDL fait beaucoup de choses spéciales pour rendre les mathématiques très rapides et avoir un faible encombrement de la mémoire. Certaines des choses que vous voulez faire peuvent déjà être mises en œuvre.

1

Je vois la question est assez ancienne, mais comme l'auteur vient d'éditer la question, c'est peut-être encore intéressant. Aussi le lien vers les données est mort, mais puisque d'autres réponses utilisent l'espace comme séparateur, je le ferai aussi.

Cette réponse montre Tie::Array::CSV qui permet un accès aléatoire à un fichier CSV (ou un autre fichier analysable avec Text::CSV).

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Tie::Array::CSV; 

## put DATA into temporary file 
## if not using DATA, put file name in $file 
use File::Temp(); 
my $file = File::Temp->new(); 
print $file <DATA>; 
## 


tie my @data, 'Tie::Array::CSV', $file, { 
    text_csv => { 
    sep_char => " ", 
    }, 
}; 

print $data[1][2]; 

__DATA__ 
1 2 3 4 5 
6 7 8 9 1 
2 3 4 5 6 
Questions connexes