Nowe posty

Autor Wątek: [Perl] wczytywanie liczb z pliku do tablicy  (Przeczytany 6079 razy)

Gosik

  • Gość
[Perl] wczytywanie liczb z pliku do tablicy
« dnia: 2013-01-11, 13:44:44 »
Mam plik.txt z danymi odzielonymi przecinkami:
12,34,56
23,4,5
12,3,4
123,1,1

Chcialabym wczytac te dane do tablicy, tak aby moc sie odwloywac do odpowiedniego elementu,

Wczytalam dane z pliku i podzielilam je wg przecinka:
open (K, 'plik.txt'); while () {
   chomp;
   $line = $_;
   @d = split(',',$line);
   push @date,\\@d;
}
  close(K);

  print @date;
  print $date[0]->[2];
Kod ten powoduje, ze mam wyswietlony trzeci element z ostatniego wiersza.

Co w tym kodzie mam zle? Dlaczego nie wyswietla mi elementu z drugiego wiersza i trzeciej kolumny?

xavery

  • Gość
[Perl] wczytywanie liczb z pliku do tablicy
« Odpowiedź #1 dnia: 2013-01-14, 12:05:18 »
No cóż... co jest źle? Właściwie wszystko poza otwieraniem pliku:) Nawet konstrukcja pętli jest nieskończona (brakuje w argumentach while()).

Na początek żelazna zasada: używaj 'use strict' i deklaruj zmienne. O wiele łatwiej byłoby czytać taki kod. Poza tym warto używać modułu Data::Dumper i patrzeć jaką strukturę danych uzyskaliśmy. Zakładając, że w pętli while czytamy handler K to otrzymujemy:

use Data::Dumper;
...
   print Dumper @date;
i wychodzi nam na koniec:

$VAR1 = [
          '123',
          '1',
          '1'
        ];
$VAR2 = $VAR1;
$VAR3 = $VAR1;
$VAR4 = $VAR1;
Czyli tablica referencji które praktycznie mają wspólny cel - ostatni wiersz w pliku.
A dzieje się tak dlatego, że do tablicy @date dopisujesz w każdym kroku iteracji niezmienną referencję do tablicy której sama zawartość się zmienia. Aby to wyeliminować należy odkładać w tablicy @date referencje zawierające kolejne wiersze plików a więc zamiast:

   @d = split(',',$line);
   push @date,\\@d;
damy to:

   push @date,[split(',',$line)];
i otrzymujemy taką strukturę:

$VAR1 = [
          '12',
          '34',
          '56'
        ];
$VAR2 = [
          '23',
          '4',
          '5'
        ];
$VAR3 = [
          '12',
          '3',
          '4'
        ];
$VAR4 = [
          '123',
          '1',
          '1'
        ];
Wtedy element $date[0]->[2] będzie tym czym oczekiwaliśmy czyli 56.

xavery

  • Gość
[Perl] wczytywanie liczb z pliku do tablicy
« Odpowiedź #2 dnia: 2013-01-14, 12:14:36 »
Jak już mamy rozwiązanie to dopiszę się tylko, że do takich celów nie trzeba pętli. Handler pliku w kontekście listowym zwraca przecież liste wierszy pliku. Po dodaniu niewielkiej ilości perlowej magii możemy uzyskać taką samą strukturę danych w jednej linijce:

my @date=map {chomp $_; [split ",",$_]} ;

$VAR1 = [
          '12',
          '34',
          '56'
        ];
$VAR2 = [
          '23',
          '4',
          '5'
        ];
$VAR3 = [
          '12',
          '3',
          '4'
        ];
$VAR4 = [
          '123',
          '1',
          '1'
        ];

Gosik

  • Gość
[Perl] wczytywanie liczb z pliku do tablicy
« Odpowiedź #3 dnia: 2013-01-17, 07:40:44 »
Bradzo dziekuje za pomoc! :)

Jednakze mam jeszcze jeden problem:

Mam 2 pliki z danymi, gdzie pierwsze kolumny w sa w postaci daty:

kolumna z 1 pliku:
11:26:11
11:26:12
11:26:13
......

kolumna z 2 pliku:

11:26:09.126
11:26:10.126
11:26:11.126
11:26:12.126
....

Chcialbym porownac poszczegolne wiersze i jesli sie zgadzaja daty, to kleje kolumny tych plikow:
 
my @tab;
 for (my $i=1; $i<=$#date; ++$i){
   for (my $j=1; $j<=$#date2; ++$j){
     if ($date[$i]->[0] ==grep(/^$_/,$date2[$j]->[1])){
     my @temp = (@{$date[$i]},@{$date2[$j]});
     open (PLIK,'>>plik.txt');
     print PLIK join ',' , @temp, "\\n";
     close PLIK;
NIestety wyskakuje blad: Use of uninitialized value in numeric eq (==) at ./fizyka.pl line 47.

Zatsanawiam sie czy moge dac warunek:
if ($date[$i]->[0] ==grep(/^$_/,$date2[$j]->[1])