perlunity.de - PERL | JAVASCRIPT | PHP | MySQL | APACHE



#!/COMMUNITY

Members: 5374
davon online: 1
weitere User: 32
Click for quality!




08.02.2012 / 22:37

Community-Member werden   |   Paßwort vergessen   |   OnlineMonitor (1) Wer ist online ... OnlineMonitor starten !
     

 

Home


PERLscripts


PHPscripts


JAVAscripts


Hilfreiches


Links2www


Newscenter


Community


Interna




Community  »  Perl: Allgemeines Forum zur Themenübersicht Themensuche Themenansicht in Thread-Modus


BeitragHashreferenz nach Anzahl Array Elemente
Seitenanfang
Hallo zusammen,

ich habe folgendes Problem.
Ich muss ein Hashreferenz aufbauen, die sich wie folgt zusammensetzt:
In einer existierenden Hashreferenz ($d) befinden sich ein Pfaddefinition(PATH) und ein Name(NAME) des niedrigsten Ordners.

Daraus möchte ich nun die folgende Hashreferenz aufbauen, jedoch mit beliebig tiefer Ordnerstruktur. Im Beispiel habe ich nur vier Ebenen dargestellt, der verwendete Ablauf müsste in einer Schleife durchgeführt werden, leider habe ich keinen Plan, wie das fuunktionieren soll. Ich hoffe Ihr könnt mir helfen.

Gruß

Slaughter

Beispiel:

my $d=undef;
$d->{1}->{PATH}="100";
$d->{1}->{NAME}="Hundert";
$d->{2}->{PATH}="100/101";
$d->{2}->{NAME}="Hunderteins";

$d->{3}->{PATH}="100/101/102";
$d->{3}->{NAME}="Hundertzwei";

$d->{4}->{PATH}="100/101/102/103";
$d->{4}->{NAME}="Hundertdrei";
my $id="PATH";
my $name="NAME";
my $tree=undef;
foreach my $l (sort {$a<=>$b} keys(%$d)){
#Teilen des Pfades, jede Nummder ein Array Element
my @k=split("/",$d->{$l}->{$id});
#Sofern sich nur ein Element in dem Array befindet => oberste Pfad Ebene
$tree->{$k[0]}->{$id}=$d->{$l}->{$id} if ( @k == 1 );
$tree->{$k[0]}->{$name}=$d->{$l}->{$name} if ( @k == 1 );
#Sofern sich zwei Elemente in dem Array befindet => zweite Pfad Ebene
$tree->{$k[0]}->{$k[1]}->{$id}=$d->{$l}->{$id} if ( @k == 2 );
$tree->{$k[0]}->{$k[1]}->{$name}=$d->{$l}->{$name} if ( @k == 2 );
#Sofern sich drei Elemente in dem Array befindet => dritte Pfad Ebene
$tree->{$k[0]}->{$k[1]}->{$k[2]}->{$id}=$d->{$l}->{$id} if ( @k == 3 );
$tree->{$k[0]}->{$k[1]}->{$k[2]}->{$name}=$d->{$l}->{$name} if ( @k == 3 );
#Sofern sich vier Elemente in dem Array befindet => vierte Pfad Ebene
$tree->{$k[0]}->{$k[1]}->{$k[2]}->{$k[3]}->{$id}=$d->{$l}->{$id} if ( @k == 4 );
$tree->{$k[0]}->{$k[1]}->{$k[2]}->{$k[3]}->{$name}=$d->{$l}->{$name} if ( @k == 4 );
}

#Hashreferenz müsste dann so aufgebaut werden:
#100->NAME=Hundert
#100->PATH=100
#100->101->NAME=Hunderteins
#100->101->PATH=100/101
#100->101->102->NAME=Hundertzwei
#100->101->102->PATH=100/101/102
#100->101->102->103->NAME=Hundertdrei
#100->101->102->103->PATH=100/101/102/103

Datum: 13.11.2007-13:35

Beitragre: Hashreferenz nach Anzahl Array Elemente
Seitenanfang

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my $d = {
1 => { PATH => "100", NAME => "Hundert" },
2 => { PATH => "100/101", NAME => "Hunderteins" },
3 => { PATH => "100/101/102", NAME => "Hundertzwei" },
4 => { PATH => "100/101/102/103", NAME => "Hundertdrei" }
};

my $tree = {};

foreach my $l (sort {$a <=> $b} keys %{$d}) {
my $data = $d->{$l};

my $local_tree = $tree;

my $full_path;
foreach my $path_part (split '/' => $data->{'PATH'}) {
$full_path .= "/$path_part";

$local_tree = $local_tree->{$path_part} ||= {};

$local_tree->{'PATH'} = $full_path;
$local_tree->{'NAME'} ||= $path_part;
}

$local_tree->{'NAME'} = $data->{'NAME'};
}

print Dumper($tree);

Sollte's tun, ich denke der Quellcode spricht fuer sich selbst, wenn nicht einfach fragen. Waere natuerlich auch rekursiv gegangen, also eine sich selbst aufrufende Subroutine, jedoch speicherintensiver und langsamer, sollte dich auch das interessieren, fragen.

Datum: 14.11.2007-03:30

Beitragre: Hashreferenz nach Anzahl Array Elemente
Seitenanfang
Hallo Dash,

ich habe leider erst jetzt Zeit gefunden, Deine Antwort zu lesen und es ist genau das was ich gesucht habe, zunächst vielen Dank dafür.

Eventuell kannst Du mir noch kurz beschreiben, was hier genau passiert:

$local_tree = $local_tree->{$path_part} ||= {};

und was eigentlich der Unterschied ist, ob ich eine Hashreferenz mit {} oder mit undef initialisiere.

Gruß

Slaughter

Datum: 15.11.2007-14:38

Beitragre: Hashreferenz nach Anzahl Array Elemente
Seitenanfang

$local_tree = $local_tree->{$path_part} ||= {};

Ich erklaere es mal an einen anderen Beispiel


my %hash = { abc => 123, xyz => undef };

my $foo = 'abc';

my $wert_von_foo = $hash{$foo} ||= 999;


diesen Code kann man auch ausfuehrlicher so schreiben:

my %hash = { abc => 123, xyz => undef };

my $foo = 'abc';

my $wert_von_foo = ( $hash{$foo} = $hash{$foo} || 999 );


Zuerst wird der Teil in den runden Klammern ausgewertet. $hash{$foo} wird das Ergebnis von $hash{$foo} || 999 zugewiesen. Hat $hash{$foo} (bzw. $hash{'abc'}) einen wahren Wert (TRUE), dann wird $hash{$foo} sich selbst zugewiesen, andernfalls der Wert 999.
$wert_von_foo bekommt dann dass Ergebnis der gesamten Auswertung, das ist entweder der Wert von $hash{$foo} wenn $hash{$foo} 'wahr' ist andernfalls 999.

Damit lassen sich Variablen mit einen Standardwert belegen. Angenommen ein Benutzer soll eine Zahl eingeben, gibt er keine Zahl ein wird automatisch ein Standardwert genommen.


print "Eine Zahl bitte: ";
my $eingabe = <STDIN>;
chomp($eingabe);

$eingabe ||= 7;


Drueckt der Benutzer nur auf Enter und gibt also keine Zahl ein, dann hat $eingabe einen boolisch falschen Wert (FALSE), $eingabe erhaelt durch die letzte Codezeile automatisch den Wert '7' ( $eingabe = $eingabe || 7 ).

Nun mal zurueck zu meinen Codestueck


$local_tree = $local_tree->{$path_part} ||= {};

dies laesst sich ausfuehrlicher so schreiben:

$local_tree->{$path_part} = ($local_tree->{$path_part} || {});

$local_tree = $local_tree->{$path_part};


Hat $local_tree->{$path_part} einen boolisch falschen Wert (FALSE) dann wird es auf einen anonymen Hash gesetzt.

Bei der Problemloesung (letzter Post) steigt durchwandert man mehrere Ebenen der Datenstruktur ($tree->{100}->{101}->{102}), $local_tree zeigt immer auf die aktuelle Ebene, in der zweiten Ebene zeigt $local_tree auf $tree->{100}->{101}.

Noch Fragen? Fragen!

Datum: 15.11.2007-20:08

Beitragre: Hashreferenz nach Anzahl Array Elemente
Seitenanfang
>> und was eigentlich der Unterschied ist, ob ich eine Hashreferenz mit {} oder mit undef initialisiere.

Wenn du eine Variable mit undef initialisierst, haben sie keinen Wert (sind undefiniert), weist du ihr aber einen anonymen Hash zu, haben sie einen Wert naemlich eine Referenz auf einen anonymen Hash und dieser Wert ist boolisch wahr (TRUE).


my $hash_ref = {};

if($hash_ref) {
print "ist wahr\n";
}
else {
print "ist falsch\n";
}


Fuehre das Beispiel aus, dann aendere die erste Zeile auf 'my $hash_ref = undef' ab und fuehre den Code noch einmal aus, vergleiche die Ergebnisse.

Datum: 15.11.2007-20:18

Beitragre: Hashreferenz nach Anzahl Array Elemente
Seitenanfang
Hallo Dash,

vielen Dank für Deine ausführliche Erklärung, jetzt habe ich es verstanden.

Gruß

Slaughter

Datum: 16.11.2007-08:23

-






-
-