Thread Verzeichnisbaum: Flaches Array mehrdimensional printen (13 answers)
Opened by root at 2005-03-26 12:20

root
 2005-04-02 22:09
#52973 #52973
User since
2003-08-15
120 Artikel
BenutzerIn
[default_avatar]
Uff! Ich hab jetzt wirklich viel drüber nachgedacht, Zettel voll gemalt und auch ein wenig programmiert. Den Code von Renee habe ich auch fast verstanden!
Mir ist noch nicht so ganz klar, wie Du die mehrdimensionalität hinbekommst.

Was tut diese Zeile genau???
Code: (dl )
    $hashref->{$key} = insert_rec($key,$sub,$hashref->{$key}) if($sub);


Selbst wenn ich es verstehe, hilft es es mir nicht so wirklich weiter, ich brauche hinterher keine mehrdimensionales Hash, sondern ein mehrdimensionaes Array!
Der Umweg über das Hash ist aber gar nicht so schlecht, weil dann keine Doppler passieren können?!

Den Data::Dumper kannte ich noch gar nicht, hab ich mir genauer angesehen, fette Sache!

Ich beschreibe mal nochmal genau mein Problem und zeige dann mal zwei Lösungsansetze die ich hatte:

Ich habe eine Datenbanktabelle für "Dateien". Es sind natürlich nur Datensätze. Ein Datensatz könnte folgende Daten enthalten:
id=1
filename=verz1/verz2/filename
content=bla bla bla
content_type=text

Ich lese die Datensätze so aus, dass ich ein mehrdimensionales Hash erhalte, der Schlüssel ist der filename.

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
    my $statement="SELECT * FROM orangeFile_files WHERE (vertrag_id=$db_vertrag_id AND status = 'ok') ORDER BY filename";
    my $sth = $dbh->prepare($statement) or die("Kann keine Abfrage ($statement) starten:$DBI::errstr");
    $sth->execute;

    my $row;
    my %flashfile = ();
    my $cnt = 0;

    while ($row = $sth->fetchrow_hashref)
    {
        my %temp=%$row;

        # Nachschauen ob der filename doppelt besteht, dann den aktuellen benutzen
        # da nur gültige aus der DB gelesen werden, können zu alte auch gelesen werden.
        # den älteren also überschrieben:
        if($flashfile{$temp{'filename'}}{'start_time'} > $temp{'start_time'}){
            if($config{'umgebung'} eq "test"){
               
 print "Datei $temp{'filename'} gibt es mit verschiedenen start_time";
            }
            next;
        }else{ # also auch wenn nur ein Datensatz für diesen Flashfile gefunden wird

            # Fügt das gefundende Hash in das HoH ein
            $flashfile{$temp{'filename'}} = { %temp };
            #push @warnungen, "Content of ".$temp{'filename'}." is ".$flashfile{$filename}{'content'};
        }

        $cnt++;
        last if $cnt > 1000000;
    }


Die Keys meines Hashs in der ersten Dimension sind also die aufzubereitenden Daten, dazu muss aber auch noch ein Link kreiert werden, der die id der "Datei" enthält, also irgendwie so aussehen muss:
Code: (dl )
my $link="?name=wert&id=".$flashfile{$filename}{'id'}; # Link um Datei anzuzeigen und zu ändern


Das ist ein Datensatz, alle Datensätze müssen in das beschriebene Array.

Hier meine Verzweifelten Ansätze:
1. quick and dirty - wie es sonst nicht meine Art ist, schäme mich auch ein bisschen:
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#! /usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use CGI::Carp 'fatalsToBrowser';

print "Content-type: text/plain\n\n";

my %hash;
my $zaehler = 0;
while(<DATA>){
    my $path = $_;
    chomp $path;
    next if($path =~ /^\s*?$/);
    $_ =~ s/^\s+//;
    $path =~ s/^\///; #/
    next if(length $path < 2);
    my ($key,$sub) = split(/\//,$path,2);
    print "key: $key | sub: ".$sub."\n";
    unless($sub){
        $hash{$key} = 0;
        next;
    }
    $hash{$key} = insert_rec($key,$sub,$hash{$key});
}


my $outputstruktur = Dumper(\%hash); # Das was für das JS ausgegeben werden soll

# Für das JS die { durch [ ersetzen
$outputstruktur =~ s/}/]/g;
#$outputstruktur =~ s/=>/,/g;
$outputstruktur =~ s/\$VAR1/var TREE_ITEMS/g; # Variablennamen für JS ändern
$outputstruktur =~ s/('\w+') => {/[$1, $zaehler/g; # quick and dirty


# Ausgabe
print $outputstruktur;

# insert_rec builds the hash recursivly.
# Parameters:
#   key of anonymous hash that has to be expanded
#   remaining path
#   reference to hash
sub insert_rec{
    my ($key2,$path,$hashref) = @_;
    my ($key,$sub) = split(/\//,$path,2);
    unless($sub){
        $hashref->{$key} = {};
        return($hashref);
    }
    #print $sub."\n";
    $hashref->{$key} = insert_rec($key,$sub,$hashref->{$key}) if($sub);
    return ($hashref);
}# end insert_rec

# ohne Leerzeichen:

verz1/datei1
verz1/datei2
verz1/datei3
verz1/datei4
file1
verz1/verz2/verz3/file1231
verz1/verz2/verz3/file1232
verz1/verz2/file121
verz1/verz2/file122
verz1/verz2/file123


2. Hab ich versuch die Nummer von dir renee mit nem Array aufzubauen. Ich bekomme aber die Dimensionen, bzw. die Tiefe nicht hin. Ich weiß nicht wie ich $link integrieren soll und hab ein bisschen Probleme, dass die Verzeichnisse in der Unteren Ebene nicht für jeden File aufs neue gepusht werden:
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#! /usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use CGI::Carp 'fatalsToBrowser';

print "Content-type: text/plain\n\n";
my $dimension; # Enthält die aktuelle Dimension des Arrays
my @element_nummer = (); # Enthält die aktuelle Position im Array, bezogen auf die Dimension
my @array_of_arrays = (); # Wird befüllt
my @AoA2 = (); # füll das erste AoA

while(<DATA>){
    $dimension = 0; # reset
    #@element_nummer=(); # reset
    # bisschen was überprüfen und aussortieren
    next if($_ =~ /^\s*?$/);
    $_ =~ s/^\s+//;
    my $path = $_;
    chomp $path;
    $path =~ s/^\///; #/
    next if(length $path < 5);
    # unterstes Verzeichnis nehmen und mit "Rattenschwanz" an Funktion insert_rec übergeben
    my ($key,$sub) = split(/\//,$path,2);
    @AoA2 = (); #reset
    push @array_of_arrays, [insert_rec($key,$sub,"ich bin der Link")];
    $element_nummer[$dimension]++;
}


my $outputstruktur = Dumper(@array_of_arrays); # Das was für das JS ausgegeben werden soll

# Für das JS die { durch { durch [ ersetzen
$outputstruktur =~ s/\$VAR1/var TREE_ITEMS/g; # Variablennamen für JS ändern


# Ausgabe
print $outputstruktur;

sub insert_rec{
    my $key2; # Datei oder Verzeichnisname in der 2. Ebene
    my $path; # Rattenschwanz des Path, überbleibende Verzeichnisse und Dateien
    my $link; # Der Link für das JavaScript
    ($key2,$path,$link) = @_;
    my ($key,$sub) = split(/\//,$path,2); # Wieder aufteilen
    unless($sub){ # Wenn es kein Sub gibt muss es eine Datei sein, also mit Infos zurückgeben
        return($key, $link);
    }
    # Hier komme ich nur hin, wenn $key ein Verzeichnis ist, $sub also existiert, weil ich vorher mit return zurück gesprungen bin.
    # und einmal rekursiv Verzeichnis in Array pushen
    #return (insert_rec($key,$sub,"ich bin ein Verzeichnis"));

    my $arraydimension; # Wie tief soll in das Array gepusht werden?
    $arraydimension = 'push @{ $AoA2';
    # Dimension anhängen
    foreach(@element_nummer){
        $arraydimension .= "[".$_."]";
    }
    $arraydimension .= " }, [ insert_rec('$key','$sub',\"ich bin ein Verzeichnis\") ]";
    print $arraydimension."\n";
    eval($arraydimension);
    # Nächstes Listenelement ist dran
    $element_nummer[$dimension]++;
    $dimension++;
    return(@AoA2);
}# end insert_rec

# Testdaten
# ohne Leerzeichen:

verz1/datei1
verz1/datei2
verz1/datei3
verz1/datei4
file1
verz1/verz2/verz3/file1231
verz1/verz2/verz3/file1232
verz1/verz2/file121
verz1/verz2/file122
verz1/verz2/file123

Ziel ist so ein Print:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var TREE_ITEMS = [
['Home', null,
['test', "Link mit id aus Datenbank"],
['verz1', null,
['file2', "Link mit id aus Datenbank"],
['verz2', null,

['ver3', "Link mit id aus Datenbank",

['file3', "Link mit id aus Datenbank"],

],
],
],
],
];


Alleine packe ich es nicht!!!
Vielen Dank, alleine schon für die Zeit diesen Beitrag in Buchlänge zu lesen :-)

DAAAAAANKE!!!\n\n

<!--EDIT|root|1112465648-->

View full thread Verzeichnisbaum: Flaches Array mehrdimensional printen