'by package' sorting of fully qualified functions

Discussion in 'Perl Misc' started by Tassilo v. Parseval, Jan 29, 2004.

  1. Hi there,

    I was in the situation to come up with a kind of special sort routine.
    The data to be sorted is a list of fully qualified function names as in

    Pack1::subpack::func2
    Pack1::subpack::func1
    Pack1::func
    __MAIN__
    Pack2::bla
    Pack1::subpack::another_subpack::func

    which ultimately should be sorted like this:

    Pack1::func
    Pack1::subpack::func1
    Pack1::subpack::func2
    Pack1::subpack::another_subpack::func
    Pack2::bla
    __MAIN__

    So essentially this should order these functions hierarchicly on their
    package name and finally on their function name. '__MAIN__' should
    always come as last element.

    I had a hard time getting it right for a seemingly simple problem such
    as this one. My solution:

    @sorted = sort bypackage @functions;

    sub bypackage {

    # make sure that __MAIN__ is always last on output
    return 1 if $a eq '__MAIN__';
    return -1 if $b eq '__MAIN__';

    my @a = split /::/, $a;
    my @b = split /::/, $b;

    my $s = '$a[0] cmp $b[0]';
    if (@a == @b) {
    $s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $#a;
    } else {
    my $min = @a < @b ? $#a : $#b;
    $s = '$a[0] cmp $b[0]';
    $s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $min-1;
    $s .= "||\@a <=> \@b";
    }
    return eval $s;
    }

    I am not so much concerned with the dog-like slowness of the above. That
    can be tolerated (the splits could be be cached to improve it a little).
    I think the wordiness doesn't make this a very elegant solution measured
    by Perl-standards.

    How would others solve this task?

    Bonus question: if speed was an issue, how could techniques such as
    the Schwartzian or Guttman-Rosler Transform be applied here?

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jan 29, 2004
    #1
    1. Advertising

  2. Tassilo v. Parseval

    Anno Siegel Guest

    Tassilo v. Parseval <-aachen.de> wrote in comp.lang.perl.misc:
    > Hi there,
    >
    > I was in the situation to come up with a kind of special sort routine.
    > The data to be sorted is a list of fully qualified function names as in
    >
    > Pack1::subpack::func2
    > Pack1::subpack::func1
    > Pack1::func
    > __MAIN__
    > Pack2::bla
    > Pack1::subpack::another_subpack::func
    >
    > which ultimately should be sorted like this:
    >
    > Pack1::func
    > Pack1::subpack::func1
    > Pack1::subpack::func2
    > Pack1::subpack::another_subpack::func
    > Pack2::bla
    > __MAIN__
    >
    > So essentially this should order these functions hierarchicly on their
    > package name and finally on their function name. '__MAIN__' should
    > always come as last element.


    That last requirement will have to be dealt with in an ad-hoc manner.
    Also, "__MAIN__" isn't a fully qualified function name. I'll ignore
    it for now.

    > I had a hard time getting it right for a seemingly simple problem such
    > as this one. My solution:
    >
    > @sorted = sort bypackage @functions;
    >
    > sub bypackage {
    >
    > # make sure that __MAIN__ is always last on output
    > return 1 if $a eq '__MAIN__';
    > return -1 if $b eq '__MAIN__';
    >
    > my @a = split /::/, $a;
    > my @b = split /::/, $b;
    >
    > my $s = '$a[0] cmp $b[0]';
    > if (@a == @b) {
    > $s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $#a;
    > } else {
    > my $min = @a < @b ? $#a : $#b;
    > $s = '$a[0] cmp $b[0]';
    > $s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $min-1;
    > $s .= "||\@a <=> \@b";
    > }
    > return eval $s;
    > }


    Gee, I must be missing something. As far as I see, you only need to
    split off the (final) function name. Sort the package parts, and within
    these sort the function names. So:

    sub bypackage {
    my ( $apack, $aname) = $a =~ /(.+)::(.+)/;
    my ( $bpack, $bname) = $b =~ /(.+)::(.+)/;
    $apack cmp $bpack or $aname cmp $bname;
    }

    [...]

    > Bonus question: if speed was an issue, how could techniques such as
    > the Schwartzian or Guttman-Rosler Transform be applied here?


    I don't need to explain how to apply the Schwartz transform to my
    suggestion. The GRT doesn't seem to apply easily, as always when
    different sort fields must be dealt with independently.

    Anno
     
    Anno Siegel, Jan 29, 2004
    #2
    1. Advertising

  3. Tassilo v. Parseval

    Ben Morrow Guest

    -aachen.de wrote:
    > Hi there,
    >
    > I was in the situation to come up with a kind of special sort routine.
    > The data to be sorted is a list of fully qualified function names as in
    >
    > Pack1::subpack::func2
    > Pack1::subpack::func1
    > Pack1::func
    > __MAIN__
    > Pack2::bla
    > Pack1::subpack::another_subpack::func
    >
    > which ultimately should be sorted like this:
    >
    > Pack1::func
    > Pack1::subpack::func1
    > Pack1::subpack::func2
    > Pack1::subpack::another_subpack::func
    > Pack2::bla
    > __MAIN__
    >
    > So essentially this should order these functions hierarchicly on their
    > package name and finally on their function name. '__MAIN__' should
    > always come as last element.

    <snip>
    > How would others solve this task?


    #!/usr/bin/perl

    $\ = $, = "\n";

    use subs qw/hier_cmp bypackage/;

    my @functions = qw/
    Pack1::subpack::func2
    Pack1::subpack::func1
    Pack1::func
    __MAIN__
    Pack2::bla
    Pack1::subpack::another_subpack::func
    /;

    sub hier_cmp {
    my @x = @{$_[0]};
    my @y = @{$_[1]};

    my ($x, $y) = (shift @x, shift @y);

    return $x cmp $y unless @x || @y;
    return 1 unless @y;
    return -1 unless @x;

    return ($x cmp $y) || hier_cmp \@x, \@y;
    }

    sub bypackage {
    return 1 if $a eq '__MAIN__';
    return -1 if $b eq '__MAIN__';

    my @a = split /::/, $a;
    my @b = split /::/, $b;

    return hier_cmp \@a, \@b;
    }

    print sort bypackage @functions;

    __END__

    I don't really like having '$x cmp $y' in there twice, but I can't see
    how to get rid of it.

    Ben

    --
    If I were a butterfly I'd live for a day, / I would be free, just blowing away.
    This cruel country has driven me down / Teased me and lied, teased me and lied.
    I've only sad stories to tell to this town: / My dreams have withered and died.
    <=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=>=<=> (Kate Rusby)
     
    Ben Morrow, Jan 29, 2004
    #3
  4. Also sprach Anno Siegel:

    > Tassilo v. Parseval <-aachen.de> wrote in comp.lang.perl.misc:
    >> Hi there,
    >>
    >> I was in the situation to come up with a kind of special sort routine.
    >> The data to be sorted is a list of fully qualified function names as in
    >>
    >> Pack1::subpack::func2
    >> Pack1::subpack::func1
    >> Pack1::func
    >> __MAIN__
    >> Pack2::bla
    >> Pack1::subpack::another_subpack::func
    >>
    >> which ultimately should be sorted like this:
    >>
    >> Pack1::func
    >> Pack1::subpack::func1
    >> Pack1::subpack::func2
    >> Pack1::subpack::another_subpack::func
    >> Pack2::bla
    >> __MAIN__


    [...]

    > Gee, I must be missing something. As far as I see, you only need to
    > split off the (final) function name. Sort the package parts, and within
    > these sort the function names. So:
    >
    > sub bypackage {
    > my ( $apack, $aname) = $a =~ /(.+)::(.+)/;
    > my ( $bpack, $bname) = $b =~ /(.+)::(.+)/;
    > $apack cmp $bpack or $aname cmp $bname;
    > }


    Embarrassingly simple really. I initially was treating the function name
    in a similar matter. But the major flaw in each of my attempts was that I
    also split the package portion instead of just leaving it intact.

    Alright, I'll retreat in shame.

    >> Bonus question: if speed was an issue, how could techniques such as
    >> the Schwartzian or Guttman-Rosler Transform be applied here?

    >
    > I don't need to explain how to apply the Schwartz transform to my
    > suggestion.


    Indeed not, thank you!

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jan 29, 2004
    #4
  5. Also sprach Ben Morrow:

    > -aachen.de wrote:
    >> Hi there,
    >>
    >> I was in the situation to come up with a kind of special sort routine.
    >> The data to be sorted is a list of fully qualified function names as in
    >>
    >> Pack1::subpack::func2
    >> Pack1::subpack::func1
    >> Pack1::func
    >> __MAIN__
    >> Pack2::bla
    >> Pack1::subpack::another_subpack::func
    >>
    >> which ultimately should be sorted like this:
    >>
    >> Pack1::func
    >> Pack1::subpack::func1
    >> Pack1::subpack::func2
    >> Pack1::subpack::another_subpack::func
    >> Pack2::bla
    >> __MAIN__
    >>
    >> So essentially this should order these functions hierarchicly on their
    >> package name and finally on their function name. '__MAIN__' should
    >> always come as last element.

    ><snip>
    >> How would others solve this task?

    >
    > #!/usr/bin/perl
    >
    > $\ = $, = "\n";
    >
    > use subs qw/hier_cmp bypackage/;
    >
    > my @functions = qw/
    > Pack1::subpack::func2
    > Pack1::subpack::func1
    > Pack1::func
    > __MAIN__
    > Pack2::bla
    > Pack1::subpack::another_subpack::func
    > /;
    >
    > sub hier_cmp {
    > my @x = @{$_[0]};
    > my @y = @{$_[1]};
    >
    > my ($x, $y) = (shift @x, shift @y);
    >
    > return $x cmp $y unless @x || @y;
    > return 1 unless @y;
    > return -1 unless @x;
    >
    > return ($x cmp $y) || hier_cmp \@x, \@y;
    > }
    >
    > sub bypackage {
    > return 1 if $a eq '__MAIN__';
    > return -1 if $b eq '__MAIN__';
    >
    > my @a = split /::/, $a;
    > my @b = split /::/, $b;
    >
    > return hier_cmp \@a, \@b;
    > }
    >
    > print sort bypackage @functions;
    >
    > __END__
    >
    > I don't really like having '$x cmp $y' in there twice, but I can't see
    > how to get rid of it.


    I kind of like that. It's the recursive implementation of what my
    function did. Yet I assume that you would have come up with a solution
    similar to Anno's if I hadn't provided my ridiculously complicated code
    that probably distracted you.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Jan 29, 2004
    #5
  6. Tassilo v. Parseval

    Bo Lindbergh Guest

    How about this: split each fully qualified name into package name and
    function name; use the package name as the key for a hash of arrays of
    function names. This lets you sort the package names first and then
    sort the function names within each package separately.

    /Bo Lindbergh
     
    Bo Lindbergh, Jan 29, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Frank Drebin

    Re: fully qualified domain name

    Frank Drebin, Aug 26, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    574
    Frank Drebin
    Aug 26, 2003
  2. Jacob Crossley
    Replies:
    0
    Views:
    407
    Jacob Crossley
    Apr 2, 2004
  3. patrimith
    Replies:
    2
    Views:
    725
    Goldfish
    Oct 11, 2007
  4. Szabolcs Borsanyi

    Pointer to qualified poitner to qualified object

    Szabolcs Borsanyi, May 30, 2008, in forum: C Programming
    Replies:
    13
    Views:
    562
    Keith Thompson
    Jun 8, 2008
  5. Sven-Thorsten Fahrbach
    Replies:
    3
    Views:
    104
    Sven-Thorsten Fahrbach
    Jul 30, 2005
Loading...

Share This Page