Toon posts:

[perl] krijg me hash niet goed gesorteerd

Pagina: 1
Acties:

Verwijderd

Topicstarter
Heej mensen,

hier: http://www.devdaily.com/perl/edu/qanda/plqa00016/ heb ik gelezen over hoe je een hash op waarde kunt sorteren. Het werkt alleen niet.

Je klikt op een leter dus bijv. a, dan ik haal dus de data van alle ringtones die met a beginnen, en stop die in een hash. (De syntax word dan: dus $TONES{idnummer} = artiest) die wil ik vervolgens op artiest sorteren en uipoepen, maar dat lukt dus nie, aaa komt onder aab te staan :(

Volgens de bovengenoemde doc, kan je hem met die subs ascending (van a-b) of descending (van b-a), maar met alletwee de subs sorteert ie descending.
code:
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
elsif ($FORM{'sort'} eq "artist") {
     foreach $line(@lines) {
            chomp($line);
            ($ringid,$cat,$artist,$title,$rtttl,$hits) = split(/\|/,$line);
            $artist = lc($artist);
            @letters = split(//,$artist);
            if ($FORM{'letter'} eq $letters[0]){
            $TONES{$ringid} = $artist;
            }
     }

foreach $key (sort hashValueDescendingNum (keys(%TONES))) {

     foreach $line(@lines) {
            chomp($line);
            ($ringid,$cat,$artist,$title,$rtttl,$hits) = split(/\|/,$line);
            if ($key eq $ringid){
             print qq~
             <Tr bgcolor=#FFFFFF>
             <Td>$artist</td>
             <Td>$title</td>
             <Td>[img]"/listen.gif"></td>
            [/img]
             ~;
            }
     }

#   print "Artiest: $TONES{$key}, id: $key\n";
}

en die subs zijn:
code:
1
2
3
4
5
6
sub hashValueDescendingNum {
   $TONES{$b} <=> $TONES{$a};
}
sub hashValueAscendingNum {
   $TONES{$a} <=> $TONES{$b};
}

Verwijderd

Topicstarter
Op zaterdag 19 januari 2002 15:04 schreef nonomen het volgende:
perlfaq 4: How do I sort a hash (optionally by value instead of key)?
Dit vond ik er:
code:
1
2
3
4
5
6
7
@keys = sort {
        $hash{$b} <=> $hash{$a}
              ||
        length($b) <=> length($a)
              ||
            $a cmp $b
    } keys %hash;

Nu komt de zooi toch in een array te staan IPV dat me hash word gesorteerd????

  • Grum
  • Registratie: Juni 2001
  • Niet online
erm returned <=> iets ? :P
volges mij niet ;)

ik heb je code niet helemaal gelezen .. maar die 2 'sort-subs' lijken me best fout omdat ze gewoon nix returnen

Verwijderd

Topicstarter
Op zaterdag 19 januari 2002 18:54 schreef Grum_ het volgende:
erm returned <=> iets ? :P
volges mij niet ;)

ik heb je code niet helemaal gelezen .. maar die 2 'sort-subs' lijken me best fout omdat ze gewoon nix returnen
Als je een hash sorteert hoeft ie niks te returnen toch? dan word gewoon de hash gesorteerd. maar is er iemand die weet hoe dat zit met die array, of is er misschien een andere oplossing voor mijn probleem.

  • tomato
  • Registratie: November 1999
  • Niet online
Eigenlijk moet je dat niet willen als ik je goed begrijp. Van values in een array kun je zeggen dat ze in een bepaalde 'volgorde' in de array staan (oplopend naar index), maar keys en values in een hash hebben natuurlijk eigenlijk geen 'volgorde'.

Wat wil je precies doen? Wil je de hash keys en values gesorteerd op value printen? Ascending:
code:
1
2
3
foreach (sort { $hash{$a} <=> $hash{b} } keys %hash) {
   print "key: $_, value: $hash{$_}"
}

Of leuker :) :
code:
1
2
map { print "key: $_, value: $hash{$_}" }
   sort { $hash{$a} <=> $hash{b} } keys %hash;

Je moet dus niet de hash zelf sorteren, maar de keys of values gesorteerd in array context zien te krijgen en mbv die (anonieme) array iets doen met je hash.

Je kunt eventueel wel een array maken met hashreferences die gesorteerd is...

Ik snap je probleem eigenlijk niet zo goed, het enige niet-triviale hieraan is dat je wilt sorteren op de hash values ipv op de keys.

Verwijderd

Topicstarter
TNx iedereen, maar het werkt nogsteeds nie ;'(
Ik hep nu dit:
code:
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
     foreach $line(@lines) {
            chomp($line);
            ($ringid,$cat,$artist,$title,$rtttl,$hits) = split(/\|/,$line);
            $artist = lc($artist);
            @letters = split(//,$artist);
            if ($FORM{'letter'} eq $letters[0]){
            $TONES{$ringid} = $artist;
            }
     }


foreach (sort { $TONES{$a} <=> $TONES{$b} } keys %TONES) {
# 
     foreach $line(@lines) {
            chomp($line);
            ($ringid,$cat,$artist,$title,$rtttl,$hits) = split(/\|/,$line);
            if ($_ eq $ringid){
            print qq~
            <tR>
            <Td>$artist</td>
            <Td>$title</td>
            <Td><img></td>
            </tr>
            ~;
            }
     }

#  print "key: $_, value: $TONES{$_}"
}
}

Verwijderd

Topicstarter
ik hep nu effe verder geklooit, de hash word wel gesorteerd, ookal zet ik de ac hoger in de lijst dan de al, komt de al toch hoger te staan, hij sorteert dus gewoon niet helemaal goed, ga zo nog eens aan de gang met de omslagtige (of hoe je dat schrijft :9) manier aan de gang met arrays enzo, eerst effe wat anders doen.

Verwijderd

Topicstarter
komp op nou mensen, heeft niemand een oplossing????

  • Ees
  • Registratie: Juli 2001
  • Laatst online: 29-07 15:00

Ees

Het (een?) probleem is dat '<=>' een numerieke vergelijking doet. Wil je op artiest of een andere string sorteren, gebruik dan 'cmp'. Verder heb ik niet naar je code gekeken, maar hopelijk kom je er zo wel uit.

Verwijderd

Topicstarter
Op maandag 21 januari 2002 14:41 schreef Ees het volgende:
Het (een?) probleem is dat '<=>' een numerieke vergelijking doet. Wil je op artiest of een andere string sorteren, gebruik dan 'cmp'. Verder heb ik niet naar je code gekeken, maar hopelijk kom je er zo wel uit.
Jaaaaaaaaaaaaaaaaaa!
het werkt! bedankt!
Maar als ik dus in een top100 het aantal hits wil sorteren moet ik <=> gebruiken??

Bedankt in iedergeval!

  • tomato
  • Registratie: November 1999
  • Niet online
poepkind: Maar als ik dus in een top100 het aantal hits wil sorteren moet ik <=> gebruiken??
<=> is een numerieke operator.
650 zal dus groter zijn dan 8.

cmp is een string operator, welke vergelijkt op ASCII waarde.
'650' zal dus kleiner zijn dan '8'.

Wanneer je op alfabet wilt sorteren, vind je het misschien nog handig om het op deze manier te doen:

lc($a) cmp lc($b)

Zodat hoofdletters genegeerd worden.
Pagina: 1