Schrift
[thread]6758[/thread]

Umbenennen von Elementen in Strukturen: eine Betrachtung



<< >> 4 Einträge, 1 Seite
Crian
 2005-03-03 18:34
#52272 #52272
User since
2003-08-04
5871 Artikel
ModeratorIn
[Homepage]
user image
Wo ich gerade im anderen Thread zum Thema Referenz / Kopie / Clone so viel mit Strukturen herumgemacht habe, kam mir die Frage, wie man eigentlich bei einem Hash wohl am elegantesten ein Element (einen Schlüssel) umbenennt.

Beim Array kann man dessen "Elemente" (das sind aber die Werte, den Schlüsseln entsprechen eigentlich die Indizes der Elemente) so umbenennen:

Code: (dl )
1
2
3
4
5
6
7
my @a1 = (qw/a b c d/);
print 'a1 : ', Dumper \@a1;

for (@a1) {
$_ = 'aa' if $_ eq 'a';
}
print 'a1 : ', Dumper \@a1;

(Oder per $a1[0] = 'aa'; falls man den Index kennt.)

Das genaue Analogon für Hashes geht so (um Werte umzubennennen):

Code: (dl )
1
2
3
4
5
6
7
my %h1 = (qw/a 1 b 2 c 3 d 4/);
print 'h1 : ', Dumper \%h1;

for (keys %h1) {
$h1{$_} = '44' if $h1{$_} eq '4';
}
print 'h1 : ', Dumper \%h1;

(Oder per $h1{d} = '44'; falls man den Schlüssel kennt.)

Was macht man aber, wenn man die Schlüssel des Hashes umbenennen will? Dabei hat man sich natürlich immer mit der Frage herumzuplagen was passieren soll, wenn es den Schlüssel schon gibt. Aber nehmen wir mal an, es gibt ihn nicht (und wir haben einen sinnvollen Grund, den Schlüssel umbenennen zu wollen).

Ich probiere mal vier Methoden aus, zwei ohne und zwei mit Erfolg.

Einfach über das Schlüssel-Array?
Code: (dl )
1
2
3
for (keys %h1) {
$_ = 'aa' if $_ eq 'a';
}

Nein, so geht es nicht, hätte mich auch überrascht.

Einfach über das Hash als Array?
Code: (dl )
1
2
3
for (%h1) {
$_ = 'aa' if $_ eq 'a';
}

so gehts auch nicht (wär auch blöd, falls a auch mal als Wert vorkommt).

Indem man einen neuen Schlüssel anlegt und den alten löscht (wahrscheinlich die naheliegendtse und langweiligste Möglichkeit)
Code: (dl )
1
2
$h1{aa} = $h1{a};
delete $h1{a};

so geht es natürlich.

Indem man in ein Array umkopiert und hinterher wieder zurück (igitt)
Code: (dl )
1
2
3
4
5
my @h1 = %h1;
for (@h1) {
$_ = 'bb' if $_ eq 'b';
}
%h1 = @h1;

so geht es natürlich auch.

Die Frage ist, gibt es eine andere (elegantere) Möglichkeit und braucht man das überhaupt?
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
Relais
 2005-03-03 19:26
#52273 #52273
User since
2003-08-06
2246 Artikel
ModeratorIn
[Homepage] [default_avatar]
[quote=Crian,03.03.2005, 17:34]Indem man einen neuen Schlüssel anlegt und den alten löscht (wahrscheinlich die naheliegendtse und langweiligste Möglichkeit)
Code: (dl )
1
2
$h1{aa} = $h1{a};
delete $h1{a};

so geht es natürlich.[/quote]
Das ließe sich dann noch saustark komprimieren:
Code: (dl )
$h1{aa} = delete $h1{a};
Erst denken, dann posten --
27. Deutscher Perl- u. Raku -Workshop (Termin wird noch gesucht) 2025 in München.

Winter is Coming
pq
 2005-03-03 19:29
#52274 #52274
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
AFAIK kam die frage auch schon mal auf perlmonks, und delete und neu anlegen ist das eleganteste, was dabei rausgekommen ist...
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
Crian
 2005-03-03 19:35
#52275 #52275
User since
2003-08-04
5871 Artikel
ModeratorIn
[Homepage]
user image
das beruhigt mich =)

@komprimierung: kewl ;-)
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
<< >> 4 Einträge, 1 Seite



View all threads created 2005-03-03 18:34.