Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

This should be trivial....what am I doing wrong? I'm trying to sort alphabetically:
#!/usr/bin/perl use warnings; use strict; my @array = (); while (<DATA>) { chomp; push @array, $_; } @array = sort { substr($a,18) cmp substr($b,18) } @array; foreach (@array) { print $_, "\n"; } __DATA__ Types;5G1xx;Attrs;ipNetToMediaType Types;5G1xx;Attrs;MAC_ADDR_OID Types;5G1xx;Attrs;sysObjectID Types;5G1xx;Attrs;ipForwarding Types;5G1xx;Attrs;EtherOutColls
Output should be:
Types;5G1xx;Attrs;EtherOutColls Types;5G1xx;Attrs;ipForwarding Types;5G1xx;Attrs;ipNetToMediaType Types;5G1xx;Attrs;MAC_ADDR_OID Types;5G1xx;Attrs;sysObjectID
Thanks!

Replies are listed 'Best First'.
Re: array substr sort ??
by TomDLux (Vicar) on Nov 07, 2003 at 16:32 UTC

    Your code works on my machine. What problems are you finding?

    update: oops, the position of the 'MAC ...'

    I wouldn't bother using substr() in the sort. It doesn't provide any benefit, only takes up time, and the sort comparison function has to traverse the string whether comparign the strings or doign the substring. Now if you were doing that oncec, at the begining of the sort ( Schwartzian Transform ), it might be worth it, but that depends on how long your list is.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: array substr sort ??
by Paulster2 (Priest) on Nov 07, 2003 at 20:59 UTC

    I don't know off the top of my head, but I do know that the PERL Cookbook has some great ideas for sorting in many different situations. They should easily be adaptable to your situation.

Re: array substr sort ??
by Anonymous Monk on Nov 07, 2003 at 16:27 UTC
    ahhh....I forgot the case sensitivity:
    @array = sort { lc substr($a,18) cmp lc substr($b,18) } @array;
    Sorry to have wasted your time
      As written, what you have is really slow. This is because sort has to call the subroutine you pass it dozens of times even for really small sets. Fortunately there is an easy and fast way to optimize it, called the schwartzian transform. It would look like this:
      @array = map { $_->[1] } sort { $a->[0] cmp $b->[0] } map { [lc substr($_,18),$_] } @array;
      What this does is first create a list of arrays, each array contains two elements, the first one is your munged data (lc,substr), and the second element is the actual data. Then you call sort and tell it to compare just the first element, that is, your munged data, then you map again to retreive just the second elements, your actual data.
        I would change it slightly to let me use the native sort:
        @array = map substr($_, 1 + index($_, "\n")), sort map lc($_) . "\n$_", @array;
        But I admit I have not done benchmarks.

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;