in Schleife Hash $key-> $value zuweisen
Andreas
- perl
Hallo!
Naja, habe wieder ein Problem welches mir in PHP kinderleicht von der Hand ging, aber mich in PERL vor ein unlösbares Problem stellt:
Am besten schreibe ich mal, wie ich es in PHP machen würde:
$array = explode("\n",$string);
foreach($array as $tmp){
list($key,$value) = explode(":",$tmp);
$mein_array[$key] = $value;
}
Wie man sieht, einen String bei "\n" teilen und somit zeilenweise in einen Array schreiben - soweit komme ich noch,
und dann in einer Schleife jedes Element dieses Arrays bei ":" teilen, und den vorderen Teil als Key und den Hintern als Value in einenHash schreiben. Mein Problem ist die Zeile
list($key,$value) = explode(":",$tmp);
das schreiben in den Hash ist klar, aber wie komme ich an die Strings $key und $value? OK, Split habt Ihr mir ja genannt, aber wie kommen die Daten jetzt als key-value ion den Hash?
Vielen Dank!
Grüße
Andreas
Halihallo Andreas
Am besten schreibe ich mal, wie ich es in PHP machen würde:
$array = explode("\n",$string);
foreach($array as $tmp){
list($key,$value) = explode(":",$tmp);
$mein_array[$key] = $value;
}
Am besten schreibe ich gleich, wie ich es in Perl machen würde: (*g*)
my @array = split( /\n/, $string );
my %mein_array; # wobei es ein Hash ist ;)
foreach my $tmp (@array) {
my ($key, $value) = split( /:/, $tmp, 2 );
$mein_array{$key} = $value;
}
Viele Grüsse
Philipp
Hi Philipp!
Am besten schreibe ich gleich, wie ich es in Perl machen würde: (*g*)
*ggg*
my @array = split( /\n/, $string );
my %mein_array; # wobei es ein Hash ist ;)
foreach my $tmp (@array) {
my ($key, $value) = split( /:/, $tmp, 2 );
das wirde in meinen Versuchen Arg komplioziert über Arrays probiert zu lösen - aber mal wieder - noch einfacher als PHP...
Danke Dir!
$mein_array{$key} = $value;
}
Die Anzahl der Elemente in einem Array, wie bekomme ich die in PERL?
Danke nochmal!
Grüße
Andreas
Halihallo Andreas ;)
$mein_array{$key} = $value;
}
Die Anzahl der Elemente in einem Array, wie bekomme ich die in PERL?
Öm. Hat das was, mit dem oberen Zitat zu tun, oder meinst du das völlig getrennt vom oberen Kontext?
Anzahl der Elemente in einem Array:
my $anzahl = @array;
so einfach ist das. Beim "skalaren" Zugriff auf ein Array, kriegst du automatisch dessen Länge zurück.
für Hashes:
Anzahl Keys: my $anzahl = keys %hash
Danke nochmal!
gleich zwei mal pro Posting??? :-))
bitte, bitte.
Viele Grüsse
Philipp
Hallo!
Noch mal was, wie um himmelswillen kommt man in PERL einigermaßen einfach an ein formatierten Datumsstring?
zunächst, localtime(time), ist time hier der unix-timestamp? Ich überlege auch ob ich Date::Calc verwende, da kann ich dann
Time_to_Date
($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
verwenden, aber was genau sagt mir diese Beschreibung? das sieht nicht wie ein Array aus, was gibt die Funktion denn dann zurück?
Gibt es da nicht sowas wie date() in PHP?
Grüße
Andreas
Halihallo Andreas
Noch mal was, wie um himmelswillen kommt man in PERL einigermaßen einfach an ein formatierten Datumsstring?
$formatted = scalar localtime();
:-)
zunächst, localtime(time), ist time hier der unix-timestamp?
genau. Und die Funktion time() liefert dir den aktuellen ;)
Ich überlege auch ob ich Date::Calc verwende, da kann ich dann
Time_to_Date
($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
Was ist denn das???? - Da gibt's ne built-in Funktion zu:
($sec, $min, $hour, $day, $month, $year, ...) = localtime(time());
oder umgekehrt:
use Time::Local qw(timelocal);
$timestamp = timelocal( $sec, $min, $hour, $day, $month, $year );
nur Achtung:
$year -= 1900; # 2002 ist 102!!
$month--; # Januar ist 0!!
verwenden, aber was genau sagt mir diese Beschreibung? das sieht nicht wie ein Array aus, was gibt die Funktion denn dann zurück?
Nun, das Modul kenne ich nicht, da ich es nicht verwende (wenn's doch built-ins hat). Aber doch, es gibt dir ein Array zurück.
@array = Time_to_Date([time]);
my ($year,$month,$day, $hour,$min,$sec) = @array;
ist genau das selbe, wie du oben beschrieben hast. Wenn du ein Array hast @tmp = qw(3 5 7); z. B., dann kannst du die Inhalte gleich in Variablen schreiben lassen: my ($first_element, $sec, $third) = @tmp; dann enthält $first_element die 3, $sec die 5 und $third die 7.
Viele Grüsse
Philipp
Hallo,
use Time::Local qw(timelocal);
$timestamp = timelocal( $sec, $min, $hour, $day, $month, $year );
nur Achtung:
$year -= 1900; # 2002 ist 102!!
$month--; # Januar ist 0!!
Um Mißverständnisse zu vermeiden:
gmtime() und localtime() liefern für das Jahr Werte ab 1900 und für das Monat Werte zwischen 0 und 11. timelocal() will genau solche Werte. Willst Du z.B. von localtime() ausgehend einen beliebigen Datumsstring formatieren, so kannst Du die Ergebniswerte im Listenkontext ($sec, $min, $hour, $day, $month, $year, ...) mit sprintf in ein das gewünschte Format bringen.
Wenn du ein Array hast @tmp = qw(3 5 7); z. B., dann kannst du die Inhalte gleich in Variablen schreiben lassen: my ($first_element, $sec, $third) = @tmp; dann enthält $first_element die 3, $sec die 5 und $third die 7.
Eigentlich eine praktische und IMHO auch intuitive Funktionalität.
BTW @Andreas:
Du hast momentan die Probleme, die jeder hat, der zum ersten mal von einer Sprache auf eine andere umsteigt. Du versuchst in Perl PHP-Code zu implementieren. Auch wenn die Syntax sehr ähnlich erscheint, so hat Perl doch einige andere Konzepte, in die Du erst hineinwachsen mußt. Mir erging es ähnlich, als ich von C her Perl anging. Aber das wird schon, und irgendwann wirst auch Du in Perl denken;-)
Grüße
Klaus
Hallo!
BTW @Andreas:
Du hast momentan die Probleme, die jeder hat, der zum ersten mal von einer Sprache auf eine andere umsteigt. Du versuchst in Perl PHP-Code zu implementieren. Auch wenn die Syntax sehr ähnlich erscheint, so hat Perl doch einige andere Konzepte, in die Du erst hineinwachsen mußt. Mir erging es ähnlich, als ich von C her Perl anging. Aber das wird schon, und irgendwann wirst auch Du in Perl denken;-)
Ja, da hast Du recht, es ist soooo nervig wenn ich genau weiß wie es in PHP geht aber in PERL Stunden dafür brauche! Habe auch direkt wieder das nächste kleine Problem, aber das weiß ich im Moment auch nicht in PHP zu lösen. Gibt es ein andere Möglichkeit die vorghandenen Elemente in einem Array zu zählen? Denn ich habe manchmal einfach nichts in den Elementen stehen und die würde ich gerne nicht mitzählen.
Und auch in diesem Zusammenhang, wie kan ich prüfen, ob ein Element eines Arrays keinen Wert enthält? Ich dachte mit if(defined $array[123]) , aber das ist irgendwie immer TRUE?!
Viele Grüße
Andreas
Halihallo Andreas
BTW @Andreas:
Du hast momentan die Probleme, die jeder hat, der zum ersten mal von einer Sprache auf eine andere umsteigt. Du versuchst in Perl PHP-Code zu implementieren. Auch wenn die Syntax sehr ähnlich erscheint, so hat Perl doch einige andere Konzepte, in die Du erst hineinwachsen mußt. Mir erging es ähnlich, als ich von C her Perl anging. Aber das wird schon, und irgendwann wirst auch Du in Perl denken;-)
Ja, da hast Du recht, es ist soooo nervig wenn ich genau weiß wie es in PHP geht aber in PERL Stunden dafür brauche! Habe auch direkt wieder das nächste kleine Problem, aber das weiß ich im Moment auch nicht in PHP zu lösen. Gibt es ein andere Möglichkeit die vorghandenen Elemente in einem Array zu zählen? Denn ich habe manchmal einfach nichts in den Elementen stehen und die würde ich gerne nicht mitzählen.
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
$cnt++;
}
Und auch in diesem Zusammenhang, wie kan ich prüfen, ob ein Element eines Arrays keinen Wert enthält? Ich dachte mit if(defined $array[123]) , aber das ist irgendwie immer TRUE?!
Ne, kann nicht sein. Das wird andere Ursachen haben. Du könntest uns den Source mal zeigen, dann könnten wir dir sagen, warum (ich hoffe, dass ich mich hier nicht irre). Aber dass ein Array mit der Länge 5 beim Index 123 bei defined true ergibt, ergibt IMO keinen Sinn.
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
next unless defined;
$cnt++;
}
kurze Erklärung:
-> next unless defined;
unless ist genau das Gegenteil von if
defined ohne Parameter verwendet den schon einmal genannte *magische* Variable $_ und somit in diesem Kontext das aktuelle Element in der Liste.
Viele Grüsse
Philipp
Hi Philipp!
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
$cnt++;
}
OK, das kannte ich
Ne, kann nicht sein. Das wird andere Ursachen haben. Du könntest uns den Source mal zeigen, dann könnten wir dir sagen, warum (ich hoffe, dass ich mich hier nicht irre). Aber dass ein Array mit der Länge 5 beim Index 123 bei defined true ergibt, ergibt IMO keinen Sinn.
ich habe mich falsch ausgedrückt. Das sieht bei mir wie folgt aus:
my @tmp_data = split /|/;
my @sorted = sort {$a<=>$b} @tmp_data;
my $min = shift @sorted;
my $max = pop @sorted;
foreach $item (@tmp_data){
chomp($item);
if (defined $item && $item==$min){
[...]
Zum Hintergrund:
Ich habe je eine Tabellen-Zeile aus der Excel-Tabelle im Array @tmp_data, den ich mit deiner Hilfe sortiert und min/max extrahiert habe. Das Problem, nicht in jeder Spalte steht ein Wert, daher hat der Array einige leere Elemente zwischendurch, vermutlich steht daher in $min 0 oder was ähnliches, da hätte ich aber gerne den niedrigsten vorhandenen Wert! Kann ich irgendwie alle leeren Elemente aus dem Array löschen? Dann wäre es kein Problem!
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
next unless defined;
$cnt++;
}
Aha, mal versuchen:
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
next unless defined;
push(@tmp_array,$_);
}
my @sorted = sort {$a<=>$b} @tmp_array;
my $min = shift @sorted;
my $max = pop @sorted;
Was sagst Du dazu? Wobei ich langsam für meinen Geschmack zu viele Schleifen verwende...
Grüße
Andreas
Halihallo Andreas
foreach $item (@tmp_data){
chomp($item);
if (defined $item && $item==$min){
[...]
Was bezweckst du damit? - Klar, $item soll definiert sein, aber warum _muss_ es dann auch noch gleich mit $min sein? - Wie setzt du $min?
Zum Hintergrund:
Ich habe je eine Tabellen-Zeile aus der Excel-Tabelle im Array @tmp_data, den ich mit deiner Hilfe sortiert und min/max extrahiert habe. Das Problem, nicht in jeder Spalte steht ein Wert, daher hat der Array einige leere Elemente zwischendurch, vermutlich steht daher in $min 0 oder was ähnliches, da hätte ich aber gerne den niedrigsten vorhandenen Wert! Kann ich irgendwie alle leeren Elemente aus dem Array löschen? Dann wäre es kein Problem!
Aha, mal versuchen:
my @array = qw( ... );
my $cnt = 0;
foreach (@array) {
next unless defined;
push(@tmp_array,$_);
}
my @sorted = sort {$a<=>$b} @tmp_array;
my $min = shift @sorted;
my $max = pop @sorted;
Was sagst Du dazu? Wobei ich langsam für meinen Geschmack zu viele Schleifen verwende...
Ist glaub ich OK.
Übrigens, wenn du schon dabei bist und über die Anzahl der Schleifen herziehst (*g*):
mach doch alles in einer und zwar ohne sort und shift und pop...
kannst ja einfach über jedes Element iterieren, next unless defined und if ($min > $_) {$min = $_} bzw if ($max < $_) {$max = $_}
Viele Grüsse
Philipp
Hi!
foreach $item (@tmp_data){
chomp($item);
if (defined $item && $item==$min){
[...]
Was bezweckst du damit? - Klar, $item soll definiert sein, aber warum _muss_ es dann auch noch gleich mit $min sein? - Wie setzt du $min?
hatte ich das nicht mitgepostet? Naja:
Min/Max des Array bestimme ich vorher in einer Schleife, so wie Du es mir mal gezeigt hast.
my @tmp_data = split /|/;
my @sorted = sort {$a<=>$b} @tmp_data;
my $min = shift @sorted;
my $max = pop @sorted;
Und ich muß das so machen, enn ich will das Minimum und das Maximum in der Ausgabe anders formatieren (daher $format_min, $format_max) in $worksheet->write(...), so habe ich z.B. das Minimum grün und das Maximum rot. Daher muß ich das auch vorher bestimmen, damit ich dann innerhalb der Schleife prüfen kann, ob das jeweilige Element das Minimum ist, und in diesem Fall ein anderes Format wählen
if (defined $item && $item==$max){
$worksheet->write($iRow - 1, $iCol, $item, $format_max);
}
elsif (defined $item && $item==$min){
$worksheet->write($iRow - 1, $iCol, $item, $format_min);
}
[...]
Das einzige Problem war jetzt noch, dass wenn vorhanden das leere/die leeren Felder das Minimum darstellten, und dem entsprechend mit grüner Schrift formatiert wurden, was ja Quatsch ist da die leer sind! Der niedrigste vorhandene Wert soll in Grün erscheinen!
Aber mit Deiner Hilfe klappt es!
kannst ja einfach über jedes Element iterieren, next unless defined und if ($min > $_) {$min = $_} bzw if ($max < $_) {$max = $_}
geht aus den oben genannten Gründen nicht!
Viele Grüße
Andreas
PS: so langsam verstehe ich auch perldoc...
Halihallo Andreas
foreach $item (@tmp_data){
chomp($item);
if (defined $item && $item==$min){
[...]
Was bezweckst du damit? - Klar, $item soll definiert sein, aber warum _muss_ es dann auch noch gleich mit $min sein? - Wie setzt du $min?
hatte ich das nicht mitgepostet? Naja:
Oh, also wenn es so ist, dann entschuldige ich mich, aber ich kann mich an dieses Vorhaben deinerseits leider nicht erinnern.
Und ich muß das so machen, enn ich will das Minimum und das Maximum in der Ausgabe anders formatieren (daher $format_min, $format_max) in $worksheet->write(...), so habe ich z.B. das Minimum grün und das Maximum rot. Daher muß ich das auch vorher bestimmen, damit ich dann innerhalb der Schleife prüfen kann, ob das jeweilige Element das Minimum ist, und in diesem Fall ein anderes Format wählen
Ach so... OK.
kannst ja einfach über jedes Element iterieren, next unless defined und if ($min > $_) {$min = $_} bzw if ($max < $_) {$max = $_}
geht aus den oben genannten Gründen nicht!
Also das bezog sich auf die Ermittlung von min und max und nicht auf das abfragen. Zuzüglich next unless defined, solltest du also mit dem zeug auch ohne pop und shift zurande kommen => wird etwas schneller. Aber so wichtig ist das ja nicht.
PS: so langsam verstehe ich auch perldoc...
jaja, da steht einiges drinne.
Viele Grüsse
Philipp
Hi!
kannst ja einfach über jedes Element iterieren, next unless defined und if ($min > $_) {$min = $_} bzw if ($max < $_) {$max = $_}
geht aus den oben genannten Gründen nicht!
Also das bezog sich auf die Ermittlung von min und max und nicht auf das abfragen. Zuzüglich next unless defined, solltest du also mit dem zeug auch ohne pop und shift zurande kommen => wird etwas schneller. Aber so wichtig ist das ja nicht.
Also so:
my @tmp_data = split /|/;
foreach (@tmp_data) {
next unless defined;
if (!defined $min || $min > $_) {$min = $_}
if (!defined $min || $max < $_) {$max = $_}
}
Viele Grüße
Andreas
Hi!
my @tmp_data = split /|/;
foreach (@tmp_data) {
next unless defined;
if (!defined $min || $min > $_) {$min = $_}
if (!defined $min || $max < $_) {$max = $_}
}
geht nicht :-( Das Problem bleibt, $min ist anscheinend irgendwas anderes.
verstehe das nicht.
Grüße
Andreas
Halihallo Andreas
my @tmp_data = split /|/;
foreach (@tmp_data) {
next unless defined;
if (!defined $min || $min > $_) {$min = $_}
if (!defined $min || $max < $_) {$max = $_}
}
geht nicht :-( Das Problem bleibt, $min ist anscheinend irgendwas anderes.
verstehe das nicht.
Ist auch unbedeutend. Was wichtig ist: durch dein Mail hab ich etwas an Überblick gewonnen => defined musst du wohl besser durch length ersetzen, da split vielleicht ein "" statt einem undef ausgibt => next unless defined wird gar nie ausgeführt...
Das und vieles andere (kleinere Tricks im Quelltext) noch per Mail.
Viele Grüsse
Philipp
Halihallo Andreas (kleiner Nachtrag)
defined musst du wohl besser durch length ersetzen, da split vielleicht ein "" statt einem undef ausgibt => next unless defined wird gar nie ausgeführt...
Wenn du folgendes splittest:
philipp|hasenfratz|philipp.ha@gmx.net||50|100
durch split /|/
@tmp = ( 'philipp', 'hasenfratz', 'philipp.ha@gmx.net', '', '50', '100');
das '' in der Mitte ist _nicht_ undef, sondern '' (leerer String).
Dies kannst du mit unless ($_) ausfiltern, jedoch nicht mit unless (defined $_). Defined liefert dir ein Boolean TRUE, wenn es wirklich undef ist, jedoch FALSE, wenn es '' oder 0 ist. Bei unless ($_) liefert dir die Bedingung TRUE, wenn $_ entweder undef oder '' oder 0 ist. Das ist der Unterschied. Du hast auch die Möglichkeit über unless length, da dann $_ als String behandelt wird (achtung aus 0 wird '0' und hat auch eine Länge!) und somit '' die Länge 0 hat => FALSE => next. In deinem Zusammenhang ist also undef length; die richtige Bedingung (auch in Anbetracht, dass Artikel eventuell den Preis 0 haben und somit die Bedingung eben auch TRUE liefern muss, was length tut, da 0 eben '0' und die Länge 1 hat)
Zurück zum splitt: Warum sollte er auch undef liefern? - Das wär ja im Kontext auch völlig falsch. Die Zeichenkette zwischen || ist ja _nicht_ undef, sondern ein _leerer_ String, undef wäre einfach falsch.
Wenn wir schon dabei sind: Ich weiss nicht genau, wie es in php geht. Seit der 4-er Version gibt's ja auch den Boolean als Typ, was es in Perl nicht gibt. Booleans haben die Werte TRUE und FALSE. In Perl musst du folgendes wissen:
die Werte undef, '' und 0 sind FALSE, alles andere TRUE (also auch '0' im String-Kontext). Das ist sozusagen die Implementation (oder wohl etwas besser: Emulation) des Boolean Datentyp in Perl.
if ($_) { ... }
dann wird { ... } also nur ausgeführt, wenn $_ einen der Werte undef, '' oder 0 hat. Wobei if (defined $_) { ... }, { ... } explizit _nur_ dann aufruft, wenn $_ _genau_ den Wert undef hat (bei '' oder 0 wird FALSE zurückgegeben).
Dies düfte für dich als php-Umsteiger noch wichtig zu wissen sein. Ich glaube, dass dies auch oft die Ursache von "komischen" Phänomenen ist...
Viele Grüsse
Philipp