Home > other >  Sort function random output
Sort function random output

Time:12-01

I'm trying to write a sort function in Perl. I need "name_iwant_last" to be the last in a sorted hash.

%libs = (
"00000000000","00000000000",
"aaaaaaaaaaa","aaaaaaaaaaa",
"AAAAAAAAAA","AAAAAAAAAA",
"name_iwant_last","name_iwant_last",
"zzzzzzzzzzzzz","zzzzzzzzzzzzz",
"ZZZZZZZZZZZ","ZZZZZZZZZZZ",
"9999999999","9999999999"
);

sub lib_sort {
  #print "cosa ordino ";
  #print $libs{$a};
  #print $libs{$b};
  #print "\n";
  return 1 if (index($libs{$a} , "name_iwant_last") != -1);
 return -1 if $libs{$a} < $libs{$b};
  return 0 if $libs{$a} == $libs{$b};
  return 1 if $libs{$a} > $libs{$b};
}

foreach my $lib (sort lib_sort values %libs) {
    print $lib;
    print "\n";
}

But, when I run this code, the print is in random order.

Expected:

aaaaa
AAAAA...
name_iwant_last

Resulted: random.

CodePudding user response:

If you add use warnings to your code, then you'll see a few warnings like this:

Argument "ZZZZZZZZZZZ" isn't numeric in numeric lt (<) at sort line 20.
Argument "AAAAAAAAAA" isn't numeric in numeric lt (<) at sort line 20.
Argument "zzzzzzzzzzzzz" isn't numeric in numeric lt (<) at sort line 20.
Argument "aaaaaaaaaaa" isn't numeric in numeric lt (<) at sort line 20.
Argument "name_iwant_last" isn't numeric in numeric lt (<) at sort line 20.

You're comparing strings, but you're using the numeric comparison operators (<, ==, >). If you switch to using string comparison operators (lt, eq, gt) then it will work as expected.

And always have use warnings and use strict in your code.

Update: As discussed in the comments, a better way to write this is to use cmp (which is the string comparison version of <=>).

sub lib_sort {

  return 1 if (index($libs{$a} , "name_iwant_last") != -1);
  return -$libs{$a} cmp $libs{$b};
}

CodePudding user response:

A working version of my code:

%libs = (
"00000000000","00000000000",
"aaaaaaaaaaa","aaaaaaaaaaa",
"AAAAAAAAAA","AAAAAAAAAA",
"name_iwant_last","name_iwant_last",
"zzzzzzzzzzzzz","zzzzzzzzzzzzz",
"ZZZZZZZZZZZ","ZZZZZZZZZZZ",
"9999999999","9999999999"
);

sub lib_sort {
  #print "cosa ordino ";
  #print $libs{$a};
  #print $libs{$b};
  #print "\n";
 if (index($libs{$a} , "name_iwant_last") != -1) { 
     return 1;
    } elsif (index($libs{$b} , "name_iwant_last") != -1) { 
     return -1;
    } elsif ($libs{$a} lt $libs{$b}) { 
     return -1;
    } elsif ($libs{$a} eq $libs{$b}) { 
     return 0;
    } elsif ($libs{$a} gt $libs{$b}) { 
     return 1;
    }
}

foreach my $lib (sort lib_sort values %libs) {
    print $lib;
    print "\n";
}
  • Related