Font
[thread]7475[/thread]

In anonymes Hash umwandeln



<< >> 10 entries, 1 page
J-jayz-Z
 2005-11-15 21:03
#60185 #60185
User since
2005-04-13
625 articles
BenutzerIn
[Homepage] [default_avatar]
Hi,
Ich hab da ein Problem. Und zwar will ich etwas in der Form X/Y/Z in ein Hash mit den Indexen ->{X}->{Y}->{Z} umwandeln.
Das Dabei ->{X}->{Y} verloren geht ist mir klar und auch in Ordnung. Mein Ansatz:
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
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $foo = &splitme("foo/lol" => "blub","foo/lol/bla" => "grml");

print Dumper($foo);

sub splitme {
my %hash = @_;
my $return;

foreach my $element(keys %hash) {
my @split=split(/\//,$element);

my $last = { };
$return = $last;

foreach my $i (0..$#split){
my $part = $split[$i];
if ($i == $#split){
$last->{$part} = $hash{$element};
}else{
$last->{$part} = { };
}
$last = $last->{$part};
}

}
return $return;
}

Kann mir da jemand helfen ?
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="5065726c2d436f6d6d756e697479"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

http://perl-tutor.de
esskar
 2005-11-15 21:13
#60186 #60186
User since
2003-08-04
7321 articles
ModeratorIn

user image
kannst du so ähnlich wie http://board.perl-community.de/cgi-bin....;t=1999 lösen
pq
 2005-11-15 22:45
#60187 #60187
User since
2003-08-04
12207 articles
Admin1
[Homepage]
user image
[quote=J-jayz-Z,15.11.2005, 20:03]
Code: (dl )
my $foo = &splitme("foo/lol" => "blub","foo/lol/bla" => "grml");

Kann mir da jemand helfen ?[/quote]
kannst du bitte mal sagen, was da herauskommen soll?
einmal soll $foo->{foo}->{lol} = "blub" sein, dann wiederum
soll aber $foo->{foo}->{lol}->{bla} = "grml" sein.
das geht nicht.
falls du dich da nur vertippt hast:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sub splitme {
   my (%pairs) = @_;
   my $hash = {};
   for my $keypath (keys %pairs) {
       my @paths = split m#/#, $keypath;
       my $value = $pairs{$keypath};
       make_hash($hash, $value, @paths);
   }
   return $hash;
}

sub make_hash {
   my ($hash, $value, @paths) = @_;        
   my $ref = \$hash;                        
   for (@paths) {
       $ref = \$$ref->{$_};
   }
   $$ref = $value;
}
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
J-jayz-Z
 2005-11-15 22:45
#60188 #60188
User since
2005-04-13
625 articles
BenutzerIn
[Homepage] [default_avatar]
Dank dir erstmal für die Antwort. Aber ich bekomm den Wert von ->{x}->{y} durch ->{x}->{z} überschrieben, wieso ist mir aber nicht besonders klar...
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
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $bla = Container->new();
$bla->blub("foo/bar" => "eins");
$bla->blub("foo/bla" => "zwei");

my $foo = $bla->getValue();

print Dumper $foo;

package Container;

sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}

sub blub {
my $self = shift;
$self->{Hash} = {};
my %foo = @_;
my @daten;
foreach(keys %foo) {
my @split = split "/", $_;
push @daten, [ @split ];
}


my $tmp_key;

foreach my $data (@daten) {
if(ref $data eq 'ARRAY') {
$tmp_key = "";
my $count = 0;
foreach(@{ $data }) {
$tmp_key .= $_;
$tmp_key .= "/" unless($_ eq $data->[-1]);
$count++;
}
my $max = scalar(@{$data});
my $start = $self->{Hash};
for my $i (1 .. $max) {
my $key = $data->[$i-1];
my $val = $i == $max ? $foo{$tmp_key} : { };
$start = _prepareOrSet($start, $key, $val);
}
}
}
}
sub _prepareOrSet {
my ($href, $key, $val) = @_;
$href->{$key} = $val unless defined $href->{$key};
return $href->{$key};
}

sub getValue {
my $self = shift;
return $self->{Hash};
}
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="5065726c2d436f6d6d756e697479"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

http://perl-tutor.de
J-jayz-Z
 2005-11-15 22:48
#60189 #60189
User since
2005-04-13
625 articles
BenutzerIn
[Homepage] [default_avatar]
[quote=J-jayz-Z,15.11.2005, 20:03]Und zwar will ich etwas in der Form X/Y/Z in ein Hash mit den Indexen ->{X}->{Y}->{Z} umwandeln.
Das Dabei ->{X}->{Y} verloren geht ist mir klar und auch in Ordnung.[/quote]
@pq: Ich hab ja geschrieben, das mir klar ist, das dabei der Wert darunter verloren geht. Sonst brächte ich ja ein Array unter dem Wert ->{X}->{Y}.Das war mir klar. Es soll immer nur der oberste Wert gesichert werden. Aber bei dem Ansatz von esskar bekomm ich irgendwie immer nur ein Index ...
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="5065726c2d436f6d6d756e697479"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

http://perl-tutor.de
sri
 2005-11-15 23:01
#60190 #60190
User since
2004-01-29
828 articles
BenutzerIn
[Homepage] [default_avatar]
Wie waer es mit nem Tree?
pq
 2005-11-15 23:04
#60191 #60191
User since
2003-08-04
12207 articles
Admin1
[Homepage]
user image
[quote=J-jayz-Z,15.11.2005, 21:48]@pq: Ich hab ja geschrieben, das mir klar ist, das dabei der Wert darunter verloren geht. Sonst brächte ich ja ein Array unter dem Wert ->{X}->{Y}.Das war mir klar. Es soll immer nur der oberste Wert gesichert werden. Aber bei dem Ansatz von esskar bekomm ich irgendwie immer nur ein Index ...[/quote]
versuch doch mal, meinen code so abzuwandeln, dass er das tut.
wichtig ist halt bei dir die reihenfolge der argumente, da wo ich
ein hash genommen hab, und du musst nachschauen, ob schon ein skalar drinsteht
und ggsf. durch {} ersetzen.\n\n

<!--EDIT|pq|1132088805-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
J-jayz-Z
 2005-11-15 23:58
#60192 #60192
User since
2005-04-13
625 articles
BenutzerIn
[Homepage] [default_avatar]
Ich weiß nicht wieso aber ich steh aufm Schlauch. Ich bekommes nicht hin :(
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="5065726c2d436f6d6d756e697479"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

http://perl-tutor.de
pKai
 2005-11-16 12:46
#60193 #60193
User since
2005-02-18
357 articles
BenutzerIn
[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
use strict;
use warnings;
use Data::Dumper ();

my $S = {};

sub splitTo {
my ($pH, $pA, $leaf) = @_;
$pA = [ grep $_, split /\//, $pA ] unless ref $pA;
return $leaf unless @$pA;
my $nxt = shift @$pA;
my $pHN = ref $pH->{$nxt} ? $pH->{$nxt} : {};
$pH->{$nxt} = splitTo($pHN, $pA, $leaf);
$pH;
}

splitTo($S, 'foo/bar', 'oops');
splitTo($S, 'foo/bar/baz', '\\o/');
splitTo($S, 'foo/gnu', 'gnat');

print Data::Dumper->Dump([$S], ['S']);
Code: (dl )
1
2
3
4
5
6
7
8
$S = {
'foo' => {
'bar' => {
'baz' => '\\o/'
},
'gnu' => 'gnat'
}
};

Hier wird allerdings gnadenlos überschrieben:
Code: (dl )
1
2
3
splitTo($S, 'foo/gnu', 'gnat');
splitTo($S, 'foo/bar/baz', '\\o/');
splitTo($S, 'foo/bar', 'oops');
Code: (dl )
1
2
3
4
5
6
$S = {
'foo' => {
'bar' => 'oops',
'gnu' => 'gnat'
}
};


Edit: Wenn überschreiben von Hashrefs durch Skalare nicht gewünscht ist, muss es in der sub
Code: (dl )
    return(keys %$pH ? $pH : $leaf) unless @$pA;
in der return-Zeile heißen.

Edit2: Und noch der Vollständigkeit halber: Wenn im Eingabepfad "0" als Teil auftreten kann, die Prüfung im grep von $_ auf length $_ umstellen\n\n

<!--EDIT|pKai|1132144291-->
I sense a soul in search of answers.
J-jayz-Z
 2005-11-17 01:14
#60194 #60194
User since
2005-04-13
625 articles
BenutzerIn
[Homepage] [default_avatar]
Okay, das ist genau das, was ich gesucht habe, danke !
perl -Mstrict -Mwarnings -e 'package blub; sub new { bless {} } sub bar {my $self=shift; $self->{bla}="5065726c2d436f6d6d756e697479"; return $self->{bla};} my $foo=blub->new();print "Hallo ";print pack("H*",$foo->bar()); print "\n"'

http://perl-tutor.de
<< >> 10 entries, 1 page



View all threads created 2005-11-15 21:03.