Schrift
[thread]6553[/thread]

Hashvalues nach Variablen sortieren: SCHWER



<< |< 1 2 3 >| >> 26 Einträge, 3 Seiten
Gast Gast
 2004-09-01 16:49
#49749 #49749
Angenommen ich habe einen Hash. Ich schreibe eine Anzeigentafel für ein Kino. In jedem Kino läuft der gleiche Film, aber an verschiedenen Tagen und Uhrzeiten. Die Keys sind die jeweiligen Kinonummern. Wie kann ich die Anzeige jetzt nach Datum und Uhrzeit sortieren, also weder nach values oder nach keys?
Ist super schwer, bin über jede Hilfe dankbar!!!
renee
 2004-09-01 17:02
#49750 #49750
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Wenn Datum und Uhrzeit nirgends festgehalten sind, wie soll man dann danach sortieren?? Das muss doch irgendwie im Hash gespeichert sein... Oder in einem anderen Hash... Irgendeine Verknüpfung zwischen Uhrzeit und Kino muss es ja geben... Zeig doch mal einen Beispielhash!
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
DayGlo
 2004-09-01 17:29
#49751 #49751
User since
2004-09-01
5 Artikel
BenutzerIn
[default_avatar]
Also ich habe eine externe Textdatei, die ist etwa so:

Code: (dl )
1
2
3
KingArthur Kino5 23.09.04 15:55
Titanic Kino6  20.09.04 20:00
Traumschiff Kino7 20.09.04 21:00


Diese Daten lese ich mit Hilfe einer Subroutine in Hashes %film, %ort, %am und %um ein. Die Values der Hashes sind die einzelnen Positionen in der Textdatei. Als keys habe ich die Kinonummern gesetzt. In einer anderen Subroutine gebe ich das aktuelle Datum und die aktuelle Uhrzeit aus. Jetzt will ich, dass die Filme halt danach sortiert werden...

edit pq: code-tags hinzugefügt\n\n

<!--EDIT|pq|1094045988-->
renee
 2004-09-01 17:40
#49752 #49752
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Einfacher wäre es, wenn Du alles in einem Hash hättest...
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
#! /usr/bin/perl

use strict;
use warnings;

my %hash = ();

while(my $line = <DATA>){
 my @array = split(/\s+/,$line);
 $hash{$array[1]} = [@array[0,2,3]];# key: kino, value: anonymes array mit film, datum, uhrzeit
}


my @sorted_keys = sort{$hash{$a}->[1] cmp $hash{$b}->[1]
                      || $hash{$a}->[2] cmp $hash{$b}->[2]}keys(%hash);

print $hash{$_}->[1]," ",$hash{$_}->[2]," ",$_," ",$hash{$_}->[0],"\n" for(@sorted_keys);



_ _DATA_ _
KingArthur Kino5 23.09.04 15:55
Titanic Kino6  20.09.04 20:00
Traumschiff Kino7 20.09.04 21:00


Ausgabe:
Quote
~/entwicklung 42> perl sort.pl
20.09.04 20:00 Kino6 Titanic
20.09.04 21:00 Kino7 Traumschiff
23.09.04 15:55 Kino5 KingArthur
\n\n

<!--EDIT|renee|1094046536-->
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
esskar
 2004-09-01 17:47
#49753 #49753
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
ich würde die datei anders einlesen; entweder nach kino, oder nach film und dann meinen hash folgendermaßen aufbauen

Code: (dl )
1
2
3
4
5
6
7
8
{ "King Arthur" =>
{ Kino => [1, 3, 4, 5, 6],
1 => [ "23.09.04 15:55", "23.09.04 20:15" ],
3 => [ "24.09.04 15:55", "24.09.04 20:15" ],
},
"Traumschiff" =>
....
};
Crian
 2004-09-01 17:59
#49754 #49754
User since
2003-08-04
5866 Artikel
ModeratorIn
[Homepage]
user image
Herzlich willkommen DayGlo / Claudia,

zum Sortieren findet man auf meiner Perlseite ein paar Snippets (http://www.duehl.de/christian/perl/perlmain.html#snipsort1 und folgende) und auf Strats Seite ein paar Tipps und Tricks (http://www.fabiani.net/perl/basics/sort.shtml).
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
Taulmarill
 2004-09-01 18:10
#49755 #49755
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
@renee: dein script hat nur probleme, wenn man daten aus unterschiedlichen monaten/jahren benutzt, da normal gesortet wird und der tag beim datum vorne steht:
Code: (dl )
1
2
3
4
5
6
7
8
9
_ _DATA_ _
KingArthur Kino5 23.09.03 15:55
Titanic Kino6 20.09.04 20:00
Traumschiff Kino7 20.09.04 21:00

Ausgabe:
20.09.04 20:00 Kino6 Titanic
20.09.04 21:00 Kino7 Traumschiff
23.09.03 15:55 Kino5 KingArthur


am besten in epoch zeit umrechnen. dafür bin ich jetzt aber zu faul :p
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
DayGlo
 2004-09-01 18:10
#49756 #49756
User since
2004-09-01
5 Artikel
BenutzerIn
[default_avatar]
Also mein problem ist viel komplizierter, glaube ich. Wollte da mit dem Kino veranschaulichen. Hier kommt mal mein Programm:
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#! perl -w
use strict;

use CGI qw/ :standard/;

my @datahashes = daten('fp.txt');     # Daten werden allen Subroutinen zugänglich gemacht


print page('Flughafen Bielefeld',print_text_html(@datahashes));   # der Seite wird der Name Flughafen gegeben, der Subroutine werden die Daten übergeben  print "$day";

sub daten {
   my $file = shift;                                      #???
   open(FILE,$file) || die "Datei $file nicht gefunden!";     # die Datei fp.txt, wie ganz oben angegeben, wird geöffnet

   my %am = my %ziel = my %von = my %gate = my %arrival = my %depart =();        # es werden leere Hashes deklariert

while ( defined (my $line = <FILE>) ) {                    # durch die while-Schleife kann die Datei Zeile für Zeile eingelsen werden
   chomp $line;                                           # chomp entfernt den Zeilenumbruch
   my @fields = split(' ', $line);                        # das array wird in zeilen zerlegt
   my $flugnr = $fields[1];                               # das 2. Element des Arrays wird als $flugnr deklariert
   $am{$flugnr} = $fields[0];                             # die restlichen Elemente werden unter dem Key flugnr abgelegt
   $ziel{$flugnr} = $fields[2];
   $von{$flugnr} = $fields[3];
   $gate{$flugnr} = $fields[4];
   $arrival{$flugnr} = $fields[5];
   $depart{$flugnr} = $fields[6];
};

close(FILE);                                                  # die Datei wird wieder zugemacht
   return (\%am,\%ziel,\%von,\%gate,\%arrival,\%depart);     # Hashreferenzen werden zurückggeben. Die Rückgabe mehrerer Hashes ist nicht möglich, weil
};                                                            # Perl diese sonst zu einem einizgen langen Hash zusammenpacken würde


sub datum_uhrzeit {                                                           #neue Subroutine
   my ($Sekunden,$Minuten, $Stunden, $Monatstag, $Monat,                    # Den Variablen wird die reale Zeit/das reale Datum übergeben
   $Jahr, $Wochentag) = localtime(time);
   my $CTIME_String = localtime(time);
   $Monat+=1;
   $Monat = $Monat < 10 ? $Monat = "0".$Monat : $Monat;
   $Monatstag = $Monatstag < 10 ? $Monatstag = "0".$Monatstag : $Monatstag;
   $Stunden = $Stunden < 10 ? $Stunden = "0".$Stunden : $Stunden;
   $Minuten = $Minuten < 10 ? $Minuten = "0".$Minuten : $Minuten;
 
   $Jahr+=1900;
   my @Wochentage = ("Sonntag","Montag","Dienstag","Mittwoch","Do
nnerstag","Freitag","Samstag");

   my $datum = "$Wochentage[$Wochentag], der $Monatstag.$Monat.$Jahr";
   my  $uhrzeit = "$Stunden:$Minuten";

   return ($uhrzeit,$datum,$Monatstag,$Monat,$Jahr);
};


sub status {
 my($am,$ziel,$von,$gate,$arrival,$depart)=@_;          #Aufruf Subroutine
 my ($uhrzeit,$datum,$Monatstag,$Monat,$Jahr) = &datum_uhrzeit();               #Aufruf Subroutine

 my ($std,$min) = split(':',$uhrzeit);                  #realeUhrzeit wird in Minuten und Stunden aufgeteilt
 my $realminutes = 60*$std + $min;                      #reale Uhrzeit wird nur noch in Minuten angegeben


  my %status=();

 foreach my $flugnr ( keys %$am ) {
 my ($stunde,$minute) = split(':',$depart->{$flugnr});  #depart-Uhrzeit wird in Minuten und Stunden aufgeteilt
 my ($departday,$departmonth,$departyear) = split('\.',$am->{$flugnr});

 my $departminutes = 60*$stunde + $minute;              #depart-Uhrzeit wird nur noch in Minuten angegeben
 my $info=$departminutes-$realminutes;
 
 my $status='';
SWITCH:
{
 if ( ($info <= -6) && ($Monatstag eq $departday) && ($Monat eq $departmonth) && ($Jahr eq $departyear) ) {
    $status="weg"; last SWITCH; };
 
 if ( ($info <= 0) && ($Monatstag eq $departday) && ($Monat eq $departmonth) && ($Jahr eq $departyear) ) {
    $status="startet"; last SWITCH; };

 if ( (($info <= 10) && ($Monatstag eq $departday)) && (($Monat eq $departmonth) && ($Jahr eq $departyear))) {
    $status="Boarding"; last SWITCH; };

 if ( (($info <= 30) && ($Monatstag eq $departday)) && (($Monat eq $departmonth) && ($Jahr eq $departyear))) {
    $status="Check in"; last SWITCH; };

    $status="am Boden";
};

 $status{$flugnr}=$status;                                              # der Status auf gestartet umspringen
};
 return %status;                                                       #$status wird zurück gegeben
};


Ich muss eine Aziegetafel für den Fulghafen schreiben, bei der die Flüge natürlich geordnet nach Datum und Uhrzeit sein müssen. Hoffe, ihr steigt da durch...
Meine Dati fp.txt sieht so aus:
Quote
30.07.2004 123456 Malaga Bielefeld C 12:15 11:31  
23.07.2004 654321 Berlin Bielefeld D 13:00 12:58
04.07.2004 587931 Barcelona Bielefeld E 14:00 12:00
30.07.2004 356987 Muenchen Bielefeld A 12:50 12:00
30.07.2004 879652 Koeln Bielefeld B 12:55 12:15
30.07.2004 456987 Bonn Bielfeld H 14:00 11:55
05.08.2004 456789 Freiburg Bielfeld C 15:00 13:00
01.09.2004 336632 Berlin Bielefeld B 22:00 19:00
\n\n

<!--EDIT|renee|1094048060-->
DayGlo
 2004-09-01 18:16
#49757 #49757
User since
2004-09-01
5 Artikel
BenutzerIn
[default_avatar]
Sorry, es fehlten natürlich noch die zwei Subroutinen, die die Seite schließlich machen:

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
sub print_text_html {                                   # Subroutine, die die Tabelle definiert

 
   my @rows = ();                                      # leere Spalten
   my($am,$ziel,$von,$gate,$arrival,$depart)=@_;       # Aufruf der daten-Subroutine, hier werden die Hasreferenzen in ein leeres Array gepackt


   my ($uhrzeit,$datum) = &datum_uhrzeit();            # Aufruf der Datum_uhrzeit Subroutine
   my $h = td ({-bgcolor=>'#66FFFF'},$uhrzeit);        # die aktuelle Uhrzeit wird einer Zabellenspalte zugewiesen

   my %status = &status(@_); #HJE
#    my $i = ();
#HJE    foreach my $status (@status) {                        # der Status (Gestartet, Boarding, Check in) aus der gleichnamigen Subroutine wird aufgerufen
#HJE    $i = td ({-bgcolor=>'#66FFFF'},$status);                # der Status wird einer Tabellenspalte zugewiesen
#HJE    };        
#HJE Kommentar: der jeweiligen Flugnummer muss der entsprechende Status $i zugeordnet werden
#HJE und nicht alllen Fluegen der in der obigen foreach-Schleife zuletzt berechnete Status
#HJE Daher muss die subroutine status ein Hash zurueckgeben, s.o.,
#HJE und "my $i =  td  ..... " muss in die folgende Schleife
  # (sort { "$Stunde:$Minute:$Monatstag:$Monat:$Jahr" <=> ) keys %$am )
   
   foreach my $flugnr ( keys %$am) {         # Schleife, um an die Werte der Hash-Referenzen heran zu kommen und damit wirklich alle Daten erfasst werden
#my @sort = &sort_nach_datum(@_);    
my $a = td({-bgcolor=>'#66FFFF'},$am->{$flugnr});        # Den einzelnen Datenwerten werden Tabellenspalten zugewiesen.  
my $b = td({-bgcolor=>'#66FFFF'},$flugnr);
my $c = td({-bgcolor=>'#66FFFF'},$ziel->{$flugnr});
my $d = td({-bgcolor=>'#66FFFF'},$von->{$flugnr});
my $e = td({-bgcolor=>'#66FFFF'},$gate->{$flugnr});
my $f = td({-bgcolor=>'#66FFFF'},$arrival->{$flugnr});
my $g = td({-bgcolor=>'#66FFFF'},$depart->{$flugnr});
my $i = td({-bgcolor=>'#66FFFF'},$status{$flugnr}); #HJE
           push(@rows,Tr($a,"\n",$b,"\n",$c,"\n",$d, "\n",$e, "\n",$f, "\n",$g, "\n",$h, "\n",$i));  #Die einzelnen Tabbellenspalten werden an die Zeilen                                                                                                      gepackt
           };
 
    return (@rows);                       # die Subroutine gibt Die Zeilen der Tabbelle zurück
};


sub page {                                             # diese Subrotuine erzeugt die eigentliche HTML-Seite

   my ($uhrzeit,$datum) = datum_uhrzeit();            # man braucht das aktuelle Datum und die reale Uhrzeit

   my ($header,@content) = @_;                         #hier wird die Seite geschrieben
   Delete_all();
   return
header,
start_html($header),
       $header = h1({-align=>'center'}, font({-color=>'#3333FF'},'Flugplan Bielefeld')),
h2 ({-align=>'center'}, $datum), hr, br, br, br, h3({-align=>'center'}, 'Abflüge'),
       table({-border=>1,-width=>'90%',-align=>'center'}, th ('Am'), th('Flug'), th('Nach'), th('Von'), th('Gate'),
             th('Ankuftzeit'), th('Abflugzeit'), th ('aktuelle Zeit'), th('Status'),
             @content),
end_html;
};


edit pq: code-tags spendiert\n\n

<!--EDIT|pq|1094048854-->
Taulmarill
 2004-09-01 18:32
#49758 #49758
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
also, unter auslassung deines geposteten codes habe ich mal ein script geschrieben, welches den von dir beschriebenen input sauber formatiert und sortiert.
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
#!/usr/local/bin/perl

use strict;
use warnings;

use Time::Local;
use POSIX qw(strftime);

my %flights;

while ( my $line = <DATA> ) {
chomp $line;
my ( $date, $num, $to, $from, $char, @times ) = split / /, $line;
my $text = "$num $to $from $char";
my ( $mday, $mon, $year ) = split /\./, $date;
for my $time (@times) {
my ( $hour, $min ) = split /:/, $time;
my $epoch = timelocal( 0, $min, $hour, $mday, $mon, $year );
push @{ $flights{$epoch} }, $text;
}
}

for my $key ( sort keys %flights ) {
my $time = strftime "%a %b %e %H:%M %Y", localtime($key);
for my $flight ( @{$flights{$key}} ) {
print "$time - $flight\n";
}
}

_ _DATA_ _
30.07.2004 123456 Malaga Bielefeld C 12:15 11:31
23.07.2004 654321 Berlin Bielefeld D 13:00 12:58
04.07.2004 587931 Barcelona Bielefeld E 14:00 12:00
30.07.2004 356987 Muenchen Bielefeld A 12:50 12:00
30.07.2004 879652 Koeln Bielefeld B 12:55 12:15
30.07.2004 456987 Bonn Bielfeld H 14:00 11:55
05.08.2004 456789 Freiburg Bielfeld C 15:00 13:00
01.09.2004 336632 Berlin Bielefeld B 22:00 19:00
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
<< |< 1 2 3 >| >> 26 Einträge, 3 Seiten



View all threads created 2004-09-01 16:49.