Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]8687[/thread]

Daten speichern in best. Datenstruktur: Aber wie?

Leser: 1


<< |< 1 2 >| >> 20 Einträge, 2 Seiten
Kalmuecke
 2007-01-26 12:36
#73713 #73713
User since
2006-10-14
68 Artikel
BenutzerIn
[default_avatar]
Hi,

ich habe folgendes Problem und zerbreche mir dabei momentan den Kopf, weil
ich nicht genau weiß wie ich meine Daten in ein Hash/Array speicheren soll,
damit ich später noch geschickt darauf zu greifen kann.

Problemstellung:
Ich habe eine Datei, die nach folgendem Muster aufgebaut ist:
ACHTUNG: Es können unterschiedliche viele Kunden existieren und jeder Kunde
hat unterschiedlich viele Datensätze.

Quote
--- Kundenname: Meyer
DatensatzA 1
DatensatzA 2
DatensatzA 3
DatensatzA 4
DatensatzA 5
DatensatzA 6

--- Kundenname: Müller
DatensatzB 1
DatensatzB 2
DatensatzB 3

--- Kundenname: Schulze
DatensatzC 1
DatensatzC 2
DatensatzC 3
DatensatzC 4
DatensatzC 5
DatensatzC 6
DatensatzC 7


Jetzt möchte ich gerne das ganze in eine Datenstruktur speichern, bei der ich
quasi durch die einzelnen Kundennamen gehen kann und dann die zum Kunden gehörenden
Daten ausgeben kann! Hintergrund: Ich muss die Datensätze später in anderen Funktionen
noch sortieren bearbeiten und dann nach bestimmten Schemen in eine HTML-Datei "drucken".
Und das geht leider nicht, in dem ich immer wieder aus der Datei lese!!!!!

Ich dachte an einen HASH. Der Schlüssel des Hash enthällt den Kundennamen und der Wert
des Hashes enthält die Adresse auf ein Array, wo die Daten zum Kunden liegen!

Hier mein bisheriger Code:

Speichern im Hash:
Code: (dl )
$kundeInfoHash{$kundenName} = [\@kundenDatenArray];


Das scheint aber nicht zu funktionieren, da ich die Datei folgendermaßen speicher und
das Script scheinbar immer wieder die gleiche Adresse vom Array speichert!

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
open(TEMP_R, '<', $tempfile) || die "Error: ";
while (<TEMP_R>)
{
  if ($_ =~ /--- Kundenname:/)
  {
     if ($kundenFound == 1)
     {
        $kundenInfoHash{$kundenName} = \@kundenMesArray; # hier passierts => immer wieder die gleiche Adresse!!!!!!!!
     }
     $kundenName = "";
     $kundenName = $_;
     $kundenName =~ s/\--- kunden:   //; # delete string "--- kunden:   " at begin of line
     $kundenName =~ s/\s\(C\)//;         # delte string " (C)" at end of line
     chomp($kundenName);                 # deletes "\n" at end of line
     $kundenName = substr($kundenName, rindex($kundenName,'\\')+1);
     push(@kundenNamesArray, $kundenName);
     $kundenFound = 1;
  }
  else
  {
     push(@kundenMesArray, $_);
  }
}
close(TEMP_R); # close TEMP-FILE


Problem ist, daß die Anzahl Kunden variieren kann!!!
Das können 10 oder auch 100 sein.
Das gleiche gilt mit den Datensätze eines jeden Kunden.

Hier noch meine Ausgabe um mal auf Datensätze eines Kunden zu zugreifen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while (my ($key, $value) = each(%kundenInfoHash))
{
  if ($key =~ "Schulze")
  {
     print $value . "\n";
     $kundenMesArrayRef = $value;
  }
}

@kundenMesArray = @$kundenMesArrayRef;

for (my $i = 0; $i < @kundenMesArray; $i++)
{
  print $i . " " . $kundenMesArray[$i] . "\n";
}


Bin für jede Hilfe dankbar!

Gruss

Kalmuecke\n\n

<!--EDIT|Kalmuecke|1169808381-->
renee
 2007-01-26 12:51
#73714 #73714
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %hash;
my $file = '/path/to/file';

{
local $/ = "\n\n---"; # mehr zu $/ siehe perldoc perlvar
open my $fh, '<',$file or die $!;
while(my $entry = <$fh>){
chomp $entry;
my ($kd,@daten) = split /\n/,$entry;
$kd =~ s/^\s*Kundennummer:\s*//;
$hash{$kd} = \@daten;
}
close $fh;
}

print Dumper(\%hash);
\n\n

<!--EDIT|renee|1169808692-->
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
renee
 2007-01-26 12:53
#73715 #73715
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
[quote=Kalmuecke,26.01.2007, 11:36][...]

Das scheint aber nicht zu funktionieren, da ich die Datei folgendermaßen speicher und
das Script scheinbar immer wieder die gleiche Adresse vom Array speichert!
[...][/quote]
Dann ist der Scope für das Array zu groß gewählt...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Kalmuecke
 2007-01-26 14:34
#73716 #73716
User since
2006-10-14
68 Artikel
BenutzerIn
[default_avatar]
Ich habe den Fehler scheinbar entdeckt, zumindest funktioniert es jetzt und mir wird alles so angezeigt wie ich möchte!

Code: (dl )
kundenInfoHash{$kundenName} = [@kundenMesArray];


Es fehlten hier die eckigen Klammern und den Backslash (Referenz) mußte ich entfernen. Jetzt übergebe ich den Inhalt eines Kunden jeweils an ein Array, welches für jeden Schlüssel des Hashes eine eigene Adresse bekommt.

@ Renee

Mhh. Schöne Sache mit dem Dumper. Ich habe mal eben die CPAN-Hilfe dazu überfolgen, aber so ganz schlau bin ich nicht geworden, wie nun Dumper zu meinem Kundennamen die Datensätze speichert!
Und wie greife ich wieder darauf zu??

Bei meinem Hash und dem Array kann ich das so schön mit Schleifen steuern!!!! Sorry, aber ich bin C-vorbelastet und einiges in Perl ist dann doch nicht so wie in Perl!

Trotzdem danke......
renee
 2007-01-26 15:59
#73717 #73717
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Dumper ist nur für die Ausgabe zuständig. Das hat mit Speichern gar nichts zu tun. Ich speichere die Datensätze in der while-Schleife ($hash{$kd} = \@daten;)...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Kalmuecke
 2007-01-26 17:26
#73718 #73718
User since
2006-10-14
68 Artikel
BenutzerIn
[default_avatar]
dann müßte bei mir die Zeile auch so heißen

Code: (dl )
kundenInfoHash{$kundenName} = \@kundenMesArray;


Aber dann speichert er nix! zumindest kann ich nicht auf die Daten zugreifen mit folgendem Code:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
 while (my ($key, $value) = each(%kundenInfoHash))
     {
           print $key . " *** " . $value . "\n";
           my @kundenMesArray = @$value;
           my $anz2 = @kundenMesArray;
          print "main: ----------->" . $anz2 . "\n";
           for (my $i = 0; $i < @kundenMesArray; $i++)
           {
              print $i . " " . $kundenMesArray[$i];
           }

     }  

cryyyyy....\n\n

<!--EDIT|Kalmuecke|1169825917-->
PerlProfi
 2007-01-27 13:27
#73719 #73719
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Du hinterlegst ja auch immer wieder die gleiche Addresse, benutz doch einfach [@kundenMesArray].
Bei renee klappt es natürlich, weil er in seinem Block ein my @daten drin stehen hat, bei dir sehe ich nicht, dass @kundenMesArray irgendwo neu deklariert wird.

Wenn du jede Zeile parsen möchtest, könntest du deinen code auch dementsprechend verändern:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# ich benutze lieber eine Variable als FH
my $hTempFile;
open($hTempFile, '<', $tempfile) || die "Error: $!";

# dieser Kundenname wird benutzt, falls Kundendaten vor
# --- Kundenname: gefunden werden
my $blockname = "default";

# und wir nehmen einen Zähler für die Kundendaten
my $counter = -1;

# $_ finde ich nicht so schön
while my$line (<$hTempFile>)
{
# Leerzeilen überspringen
next if $line =~ /^\s*$/;

# jetzt kannst du auf einen Kunden prüfen
if ($line =~ /^\s*---\s*Kundenname:\s*(.+?)\s*$/)
{
$counter = -1;
$blockname = $1;
$kundenInfoHash{$blockname} = [] if ! exists($kundenInfoHash{$blockname});
}

# oder eben auf Daten
elsif ($line =~ /^\s*(.+?)\s*$/)
{
my $daten = $1;
$counter++;
$kundenInfoHash{$blockname}->[$counter] = $daten;
}
}
close($hTempFile); # close TEMP-FILE


edit: ein paar Leerzeichen wieder eingefügt, wieso schneidet das Forum Leerzeichen vom Anfang der Zeilen weg?

MfG PerlProfi\n\n

<!--EDIT|PerlProfi|1169897404-->
Ronnie
 2007-01-27 13:52
#73720 #73720
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Du könntest auch leicht CPAN:YAML daraus machen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/perl

use strict;
use warnings;

use YAML;
use Data::Dumper;

my $ref = [Load(<<'...')];
---
Kundenname: Meyer
Datensatz:
- DatensatzA 1
- DatensatzA 2
- DatensatzA 3
- DatensatzA 4
- DatensatzA 5
- DatensatzA 6
---
Kundenname: Müller
Datensatz:
- DatensatzB 1
- DatensatzB 2
- DatensatzB 3

---
Kundenname: Schulze
Datensatz:
- DatensatzC 1
- DatensatzC 2
- DatensatzC 3
- DatensatzC 4
- DatensatzC 5
- DatensatzC 6
- DatensatzC 7);
...

print Dumper($ref);

Ergebnis sähe dann so aus:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$VAR1 = [
{
'Datensatz' => [
'DatensatzA 1',
'DatensatzA 2',
'DatensatzA 3',
'DatensatzA 4',
'DatensatzA 5',
'DatensatzA 6'
],
'Kundenname' => 'Meyer'
},
{
'Datensatz' => [
'DatensatzB 1',
'DatensatzB 2',
'DatensatzB 3'
],
'Kundenname' => 'Müller'
},
{
'Datensatz' => [
'DatensatzC 1',
'DatensatzC 2',
'DatensatzC 3',
'DatensatzC 4',
'DatensatzC 5',
'DatensatzC 6',
'DatensatzC 7;'
],
'Kundenname' => 'Schulze'
}
];

Und man kann es auch wieder als YAML ausgeben.\n\n

<!--EDIT|Ronnie|1169898830-->
bloonix
 2007-01-27 16:05
#73721 #73721
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Was spricht gegen eine Datenbank?

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
CREATE DATABASE Kalmuecke;
use Kalmuecke;
GRANT ALL PRIVILEGES ON Kalmuecke.* TO 'Kalmuecke'@'localhost' IDENTIFIED BY 'passwort';

CREATE TABLE kunden (
  kunde VARCHAR(255) NOT NULL,
  datensatz VARCHAR(255) NOT NULL,
  INDEX kunde_idx(kunde)
) TYPE=InnoDB;

INSERT INTO kunden values ('Meyer', 'DatensatzA 1');
INSERT INTO kunden values ('Meyer', 'DatensatzA 2');
INSERT INTO kunden values ('Meyer', 'DatensatzA 3');
INSERT INTO kunden values ('Meyer', 'DatensatzA 4');
INSERT INTO kunden values ('Meyer', 'DatensatzA 5');
INSERT INTO kunden values ('Meyer', 'DatensatzA 6');
INSERT INTO kunden values ('Müller', 'DatensatzB 1');
INSERT INTO kunden values ('Müller', 'DatensatzB 2');
INSERT INTO kunden values ('Müller', 'DatensatzB 3');
INSERT INTO kunden values ('Schulze', 'DatensatzC 1');
INSERT INTO kunden values ('Schulze', 'DatensatzC 2');
INSERT INTO kunden values ('Schulze', 'DatensatzC 3');
INSERT INTO kunden values ('Schulze', 'DatensatzC 4');
INSERT INTO kunden values ('Schulze', 'DatensatzC 5');
INSERT INTO kunden values ('Schulze', 'DatensatzC 6');
INSERT INTO kunden values ('Schulze', 'DatensatzC 7');


Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use DBI;

my %db = (
  name => 'Kalmuecke',
  user => 'Kalmuecke',
  pass => 'passwort',
  host => 'localhost',
  port => 3306,
  type => 'mysql',
);

my $kunde  = $ARGV[0] || die "Usage: $0 <kunde>\n";
my $select = "select datensatz from kunden where kunde = '$kunde'";

my $con = "DBI:$db{type}:database=$db{name};host=$db{host};port=$db{port}";
my $dbh = DBI->connect($con, $db{user}, $db{pass}) or die DBI->errstr;
my $sth = $dbh->prepare($select) or die $dbh->errstr;

$sth->execute() or die $sth->errstr;

my %kunden;

while (my $msg = $sth->fetchrow_hashref) {
  push @{$kunden{$kunde}}, $msg->{datensatz};
}

$sth->finish or die $sth->errstr;
$dbh->disconnect or die $dbh->errstr;

print Dumper(\%kunden);


~> ./zeige-kunde Schulze
$VAR1 = {
         'Schulze' => [
                        'DatensatzC 1',
                        'DatensatzC 2',
                        'DatensatzC 3',
                        'DatensatzC 4',
                        'DatensatzC 5',
                        'DatensatzC 6',
                        'DatensatzC 7'
                      ]
       };
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
renee
 2007-01-27 16:15
#73722 #73722
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Dann sollte man aber die ?-Schreibweise von CPAN:DBI verwenden:
Code: (dl )
1
2
3
4
5
6
7
my $select = "select datensatz from kunden where kunde = ?";

my $con = "DBI:$db{type}:database=$db{name};host=$db{host};port=$db{port}";
my $dbh = DBI->connect($con, $db{user}, $db{pass}) or die DBI->errstr;
my $sth = $dbh->prepare($select) or die $dbh->errstr;

$sth->execute($kunde) or die $sth->errstr;
Sonst darfst Du O'Reilly nie als Kunden haben...

(oder alternativ quote von CPAN:DBI verwenden)
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
<< |< 1 2 >| >> 20 Einträge, 2 Seiten



View all threads created 2007-01-26 12:36.