PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hashvalues in neuen Hash


Timi79
02.06.2008, 10:58
Servus,

Mal ne Frage. Ich habe zwei Subroutinen in denen jweils ein Hash (anonymer) mit Werten gefüllt wird.

Mich interessieren aber jeweils nur die Values der Hashes und möchte ich diese jetzt in einen neuen Hash tun, so das einer Key und der andere Value wird.

Geht das und wenn ja wie mache ich das am besten?

Danke


Alamar
02.06.2008, 13:10
Vorausgesetzt sie haben gleich viele Einträge ja.

Timi79
02.06.2008, 13:45
Jepp....die haben gleich viele Einträge!

Wie macht man das nun? Im Hauptprogramm verknüpfen oder in einer extra Routine?.....muss hier auch mich Referenzen arbeite, was das ganze noch zusätzlich erschwert.

Versuchs mir bitte erstma so zu erklären, bevor ich unnötig Code poste.

Danke

EDIT: Zur zeit sehen die Einträge folgendermaßen aus
HASH 1
1.1.1 => Name1
1.1.2 => Name2

HASH 2
1.2.1 => Wert1
1.2.2 => Wert2

...das müsste jetzt so ein, dass jetzt Name1 (neuer Key) und Wert1 der Value dazu passt.


EDIT2: Hat sich erledigt. Habs hinbekommen!

Alamar
02.06.2008, 18:35
Das ist ansich aber nicht ganz trivial weil hashes unsortiert sind das heißt wenn
die Relation Name1=>Wert1 nicht zufällig sein soll muss man da eventuell ein paar Dinge beachten. Abgesehen davon ist es der Community gegenüber nett wenn man die Lösung die man gefunden hat beschreibt/erläutert damit Leute mit ähnlichen Problemen besser geholfen ist.

Timi79
03.06.2008, 00:12
In meinem Fall war es so, dass jeweils die letzte Zahl eines Keys in beiden Hashes gleich was. Daraufhin habe ich einen Vergleich mit zwei verschachtelten Schleifen gemacht. Die erste Schleife merkt sich die letzte Zahl und in der zweiten findet der Vergleich mit Keys (letzte Zahl) statt.

Code kann ich bei Bedarf gern noch posten.


Jetzt habsch aber nochmal ne andere Frage. Wie schreibe ich einen Hash mit Key und Value in eine Datei?

thx

Alamar
03.06.2008, 00:24
Indem du die Datei öffnest und eine Abbildung ala
Key Value
oder
Key => Value
in die Datei schreibst:


open(HASHCACHE,">hashcache.txt") || die "Can't open hashcache.txt: $!";
foreach $keyval (keys(%hash)) {
print HASHCACHE "$keyval $hash{$keyval}\n";
}
close HASHCACHE;

eViL_oNe
04.06.2008, 00:41
In meinem Fall war es so, dass jeweils die letzte Zahl eines Keys in beiden Hashes gleich was. Daraufhin habe ich einen Vergleich mit zwei verschachtelten Schleifen gemacht. Die erste Schleife merkt sich die letzte Zahl und in der zweiten findet der Vergleich mit Keys (letzte Zahl) statt.


es wäre vielleicht interessant, wenn du zu diesem Weg auch das Ziel beschreibst, damit man beurteilen kann, ob beide zueinander passen. Hashes mit linearen Suchen zu beackern klingt für mich jedenfalls erstmal nicht nach state-of-the-art ;)

Timi79
04.06.2008, 09:28
Danke Alamar!

@eViL_oNe
es wäre vielleicht interessant, wenn du zu diesem Weg auch das Ziel beschreibst, damit man beurteilen kann, ob beide zueinander passen. Hashes mit linearen Suchen zu beackern klingt für mich jedenfalls erstmal nicht nach state-of-the-art ;)

Wie könnte man es denn besser machen? Muss dazu sagen, dass ich kein Perlprofi bin und sicher den umständlichsten Weg gegangen bin. Aber zumindest funzt es, dass steht bei mir erstmal an erster Stelle.

Verbesserungsvorschläge nehme ich aber gern entgegen.

mfg
Timi

Jan Krüger
04.06.2008, 10:25
Jetzt habsch aber nochmal ne andere Frage. Wie schreibe ich einen Hash mit Key und Value in eine Datei?
Wenn du die Sachen später auch nochmal mit einem Script auslesen willst, schau dir die Perl-Module Data::Dumper und Storable an.

Timi79
04.06.2008, 15:08
thx....

Das mit der Datei hat sich erledigt. Ist zum umständlich für mein Vorhaben.

eViL_oNe
04.06.2008, 22:31
Wie könnte man es denn besser machen? Muss dazu sagen, dass ich kein Perlprofi bin und sicher den umständlichsten Weg gegangen bin. Aber zumindest funzt es, dass steht bei mir erstmal an erster Stelle.

Verbesserungsvorschläge nehme ich aber gern entgegen.

mfg
Timi


da du nirgendwo schreibst, was du damit eigentlich erreichen willst, kann man auch schlecht Verbesserungsvorschläge benennen.

Timi79
06.06.2008, 09:33
OK....dann mal bissl was zum Hintergrund.

Über SNMP frage ich zum einen den Interfacestatus und zum anderen den Inferfacenamen ab. Beides gibt einen Hash in der Form von.....

OID --------------> Value
1.1.1.1 ----------> up
1.1.1.2 ----------> down

und
OID -------------> Value
1.1.2.1 ---------> eth0
1.1.2.2 ---------> eth1

zurück.
Die OID ist natürlich länger, aber soll ja nur ein BSP sein. Da mir das aber so nix nutzt und für mich nur die Values beides Hashes interessant sind (für die Ausgabe), muss ich ja die beiden Hashes irgendwie vereinen. Jetzt erkennt man, dass jeweils die letzte Ziffer der OID's in beiden Hashes gleich ist und diese zusammen gehören. d.h. OID 1.1.1.1 gehört zu 1.1.2.1, was wiederrum anzeigt, das der Status von eth0 "up" ist usw.

Und wie oben schon gesagt, nehme ich mir in der ersten Schleife die 1.1.1.1 vor....merke mir jetzt die letzte Zahl (die 1) und in der zweiten Schleife durchlaufe ich alle OID's mit 1.1.2.x und suche mir dort die 1 und speichere alles in einem neuen Hash.

eViL_oNe
06.06.2008, 21:55
der bessere Ansatz sollte sein, wenn du gleich beim Abrufen der Werte den Hashkey entsprechend "normalisierst"

Aus deinen Ausführungen schließe ich, dass die Normalisierungsfunktion folgende wäre:

1. splitte den key mit separator '.'
2. neuer key => vierter (oder auch letzter) split-wert

mit diesem Wissen kannst du erstmal beide Hashes normalisieren. Danach haben beide die gleichen Keys so dass der Rest einfach sein sollte!

#!/usr/bin/perl

use strict;

my %hash1 = (
"1.1.1.1" => "up",
"1.1.1.2" => "down"
);

my %hash2 = (
"1.1.2.1" => "eth0",
"1.1.2.2" => "eth1"
);

sub normalizeKey
{
my ($keyToNormalize) = @_;
my @keyList = reverse(split(/\./, $keyToNormalize));
return $keyList[0];
}

sub normalizeHash
{
my ($hashRef) = @_;
my %normalizedHash;
foreach my $key(keys(%{$hashRef}))
{
$normalizedHash{normalizeKey($key)} = $hashRef->{$key};
}
return %normalizedHash;
}

my %networks;

%hash1 = normalizeHash(\%hash1);
%hash2 = normalizeHash(\%hash2);

foreach my $key(keys(%hash1))
{
$networks{$hash2{$key}} = $hash1{$key};
}

foreach my $key(keys(%networks))
{
print "$key -> " . $networks{$key} . "\n";
}

Ausgabe:

eth1 -> down
eth0 -> up



Nutzen: Eine verschachtelte foreach-Schleife hat natürlich die Komplexität O(n²). Hier haben wir drei einfache foreach-Schleifen und damit die Komplexität O(n) (vorausgesetzt, die split-Funktion hat konstante Ausführungszeit -- notfalls kann man sich hier noch sicherlich einen Geschwindigkeitszuwachs mit string-Operationen statt regex-Matching erkaufen!). Dies ist für größere Datenmengen optimaler!

Timi79
06.06.2008, 23:50
Vielen Dank....werds mal austesten....morgen dann ;)