Avatar billede shale Nybegynder
16. juni 2003 - 09:42 Der er 20 kommentarer

Problemer med sortering af hash

Godmorgen eksperter :D

Jeg sidder med et lille problem med en sortering og håber at nogen herinde har en evt. løsning.

Først vil jeg lige refere til dette spørgsmål som jeg fik besvaret og det er nu det jeg gerne vil have lidt yderligere hjælp til: http://www.eksperten.dk/spm/352592

Mit problem er at jeg ikke alligevel vil have sorteret efter nummeret, men istedet den kombination af bogstaver/tal som er foran (fx. MP1, MP2 osv.). Det i sig selv er ikke noget problem, MEN når man bruger det at sortere efter sker der en fejl.
Når tallet bagefter bogstaverne kommer over 9 begynder der at ske sære ting. Tager et eksempel:

C10  A 4000457  0    0 P      0    0    0
C11  A 4010421  0    0 P      0    0    0
C12  A 4010421  0    0 P      0    0    0
C13  A 4201163  0    0 P      0    0    0
C14  A 4201163  0    0 P      0    0    0
C15  A 4000461  0    0 P      0    0    0
C16  A 4000461  0    0 P      0    0    0
C17  A 4000461  0    0 P      0    0    0
C18  A 4000461  0    0 P      0    0    0
C1    A 4010421  0    0 P      0    0    0
C19  A 4000461  0    0 P      0    0    0
C20  A 4000461  0    0 P      0    0    0
C24  A 4000404  0    0 P      0    0    0
C26  A 4000404  0    0 P      0    0    0
C27  A 4001135  0    0 P      0    0    0
C28  A 4001135  0    0 P      0    0    0
C2    A 4010421  0    0 P      0    0    0
C29  A 4000461  0    0 P      0    0    0
C30  A 4000461  0    0 P      0    0    0
C31  A 4000461  0    0 P      0    0    0
C3    A 4010316  0    0 P      0    0    0
C32  A 4010316  0    0 P      0    0    0
C33  A 4010316  0    0 P      0    0    0
C34  A 4010419  0    0 P      0    0    0
C35  A 4010419  0    0 P      0    0    0
C36  A 4000461  0    0 P      0    0    0
C37  A 4000461  0    0 P      0    0    0
C38  A 4010334  0    0 P      0    0    0
C40  A 4001135  0    0 P      0    0    0
C4    A 4201163  0    0 P      0    0    0
C41  A 4001135  0    0 P      0    0    0
C42  A 4001135  0    0 P      0    0    0

---
Som det kan ses ser det ud til at tallene under 10 bliver placeret en smule tilfældigt fx 4 midt i 40'er rækkerne osv.

Og det er DET der er mit problem, og jeg vil gerne vide hvordan man evt. kan løse det (hvis man da kan).

På forhånd tak.
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 10:34 #1
Er det altid "eet bogstav + nogle cifre"?

Vi kan sagtens finde en løsning ;)
Avatar billede shale Nybegynder
16. juni 2003 - 10:36 #2
Well nej, der kan også være 2 bogstaver, fx MP1, MP2, IC23 osv.
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 13:23 #3
Nu læste jeg lige det andet spørgsmål - der skal sorteres primært efter
tallet, sekundært efter bogstaverne?
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 13:35 #4
Det er næppe verdens mest elegante kode, men den gør det vist:

sub comp {
($a,$b) = @_;
$a=~/^(\d+)(.*)$/; $tal1=$1; $text1=$2;
$b=~/^(\d+)(.*)$/; $tal2=$1; $text2=$2;

if ($tal1<$tal2) {
  return -1;
} elsif ($tal1>$tal2) {
  return 1;
} elsif ($text1 le $text2) {
  return -1;
} elsif ($text1 ge $text2) {
  return 1;
} else {
  return 0;
}


}

$tabel{'4C'}  = "C4 ...";
$tabel{'10C'} = "C10 ...";
$tabel{'20C'} = "C20 ...";
$tabel{'4D'}  = "D4 ...";
$tabel{'10D'} = "D10 ...";
$tabel{'20D'} = "D20 ...";


foreach (sort { comp($a,$b) } keys %tabel) {
  print $tabel{$_};
}
Avatar billede shale Nybegynder
16. juni 2003 - 13:35 #5
Nej der skal helt ses bort fra tallene.

Det der skal sorteres på er C1, C2, C3 C14 osv osv... Jeg viser dig lige et andet afsnit

C38  A 4010334  0    0 P      0    0    0
C40  A 4001135  0    0 P      0    0    0
C4    A 4201163  0    0 P      0    0    0
C41  A 4001135  0    0 P      0    0    0
C42  A 4001135  0    0 P      0    0    0
C5    A 4130307  0    0 P      0    0    0
C6    A 4130307  0    0 P      0    0    0
C7    A 4000457  0    0 P      0    0    0
C8    A 4130307  0    0 P      0    0    0
C9    A 4130307  0    0 P      0    0    0
D1    A 8301045  0    0 P      0    0    0
D2    A 8301065  0    0 P      0    0    0
D3    A 8301036  0    0 P      0    0    0
D4    A 8301035  0    0 P      0    0    0
D5    A 8301045  0    0 P      0    0    0
D6    A 8301045  0    0 P      0    0    0
D7    A 8301065  0    0 P      0    0    0
IC1  A 8341022  0    0 P      0    0    0
IC2  A 8343955  0    0 P      0    0    0
IC3  A 8341022  0    0 P      0    0    0
P66  A 7211227  0    0 P      0    0    0
P67  A 7210689  0    0 P      0    0    0
P68  A 7210689  0    0 P      0    0    0
R10  A 5013063  0    0 P      0    0    0
R11  A 5013246  0    0 P      0    0    0
R116  A 5011940  0    0 P      0    0    0
R12  A 5013246  0    0 P      0    0    0
R13  A 5013225  0    0 P      0    0    0
R1    A 5013063  0    0 P      0    0    0
R14  A 5013225  0    0 P      0    0    0
R15  A 5013257  0    0 P      0    0    0

--
Som vist bliver der sorteret efter bogstavsgrupperne, men det skulle jo gerne være sådan at R1 kommer til at stå før R10 og R116 skulle gerne stå meget længere nede af listen
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 13:49 #6
Det gør det kun nemmere...

sub comp {
  ($a,$b) = @_;
  $a=~/^(\d+)/; $tal1=$1;
  $b=~/^(\d+)/; $tal2=$1;
  return $tal1 <=> $tal2;
}

$tabel{'4C'}  = "C4 ...";
$tabel{'10C'} = "C10 ...";
$tabel{'20C'} = "C20 ...";
$tabel{'4D'}  = "D4 ...";
$tabel{'10D'} = "D10 ...";
$tabel{'20D'} = "D20 ...";


foreach (sort { comp($a,$b) } keys %tabel) {
  print $tabel{$_};
}
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 13:58 #7
Eller den hurtige løsning (jeg tænkte mig ikke lige om ...):

$tabel{'4C'}  = "C4 ...";
$tabel{'10C'} = "C10 ...";
$tabel{'20C'} = "C20 ...";
$tabel{'4D'}  = "D4 ...";
$tabel{'10D'} = "D10 ...";
$tabel{'20D'} = "D20 ...";


foreach (sort { $a <=> $b } keys %tabel) {
  print $tabel{$_};
}
Avatar billede shale Nybegynder
16. juni 2003 - 14:06 #8
Problemet er at den liste jeg bruger er dynamisk og jeg kan ikke vide hvilke dele der rent faktisk står i listen :(

Listen bliver lavet ud fra et program der laver den liste der står øverst i mit tidligere spørgsmål.
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 14:19 #9
Du skal bare skrive
foreach (sort { $a <=> $b } keys %tabel) {
  print $tabel{$_};
}
i stedet for den foreach der er i dit andet spørgsmål. Mine testdata må
du gerne ignorere ;)
Avatar billede shale Nybegynder
16. juni 2003 - 14:33 #10
Hoho du har gjort mig en smuuuule forvirret nu :D

hvor får du lige $a og $b fra?
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 15:01 #11
Det er magi.

Det er det faktisk. Rent Harry Potter. Det er de navne, der bliver
brugt af 'sort'-funktionen, og de er en fast bestanddel af Perl.
Ikke specielt kønt, men ganske funktionelt. "Perlium laviosum"
Avatar billede shale Nybegynder
16. juni 2003 - 15:20 #12
Hmm jeg må nok indrømme at det der ikke virker
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 15:30 #13
Hvordan ikke virker. Mit lille eksempel virker så vidt jeg kan se.
Avatar billede shale Nybegynder
16. juni 2003 - 15:37 #14
Well den sorterer ikke listen overhovedet når jeg indsætter det ovenstående.

du kan lige få hele slamkoden :D

my @inputarray;
my $i;
my @values;
my $tabel;
my $errors;

open(INPUTFILE, "<$ARGV[2]") || die "Error opening input BOM file: $ARGV[2]\n$!";
@inputarray = <INPUTFILE>;
close(file);

open(OUTPUTFILE, ">>$ARGV[0]") || die "Error opening output BOM file: $ARGV[0]\n$!";
shift @inputarray;
pop @inputarray;
pop @inputarray;

open(LOGFILE, ">$ARGV[1]") || die "Error opening input BOM file: $ARGV[1]\n$!";

$i=0;
foreach (@inputarray)
{
  @values=split(/\s*,\s*/, $_);
  if ($values[2]!="[0-9]")
    {
    $tabel{sprintf("%-10d%s%d", $values[1], $values[1], $i)}=sprintf("%-6sA %-9s 0    0 P      0    0    0\n", $values[1], $values[2]);
    }
    else
    {
        $errors{sprintf("%-10d%s%d", $values[1], $values[1], $i)}=sprintf("%-6s med Part Number = %-9s fjernet fra BOM pga. ikke-numerisk Part Number\n", $values[1], $values[2]);
    }
  $i++;   
}

foreach (sort { $a <=> $b } keys %tabel) {
  print OUTPUTFILE $tabel{$_};
}
#foreach (sort keys %tabel)  {
#  print OUTPUTFILE $tabel{$_};
#}

foreach (sort keys %errors) {
    print LOGFILE $errors{$_};
}
Avatar billede erikjacobsen Ekspert
16. juni 2003 - 15:45 #15
Men det virker måske hvis du skriver det korrekt af fra det andet
spørgsmål. Det er da værd at prøve.
Avatar billede shale Nybegynder
16. juni 2003 - 17:37 #16
det vil jeg lige prøve i morgen
Avatar billede shale Nybegynder
17. juni 2003 - 10:52 #17
Hmm ved at indsætte din foreach i koden bliver listen overhovedet ikke sorteret?

Det kan selvfølgelig være mig der er en kegle, men synes nu ikke rigtigt at jeg kan få det til at du'.
Avatar billede erikjacobsen Ekspert
18. juni 2003 - 21:10 #18
I koden ovenover her:
  $tabel{sprintf("%-10d%s%d", $values[1], $values[1], $i)}=sprintf("%-6sA %-9s 0    0 P      0    0    0\n", $values[1], $values[2]);
ville jeg umiddelbart tro at et "1" skal skiftes ud med et "2", ganske
som der står i koden i det andet spørgsmål.

Jeg troede du fangede den med det samme....
Avatar billede shale Nybegynder
19. juni 2003 - 09:13 #19
Well det gjorde jeg også, og har prøvet med begge dele med samme resultat: ingen sortering
Avatar billede erikjacobsen Ekspert
19. juni 2003 - 22:13 #20
Hvad skriver du?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester