[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[FWP] sifting



On DALnet #perl this morning, someone was asking how to use sort() to sort
only so far as to get elements containing "gnome/" and "session" to the
front, and such that "gnome/" elements preceed "session" elements.

I said he wanted a sifting-like function, not a sorting one.

I came up with three, and benchmarked them.

My first attempt:

  # orig_sift(\@list, qr/RE/, qr/RE/, ...)
  sub orig_sift {
    my ($aref,$i) = (shift,0);
    my %pos = map { ($_, $i++) } @_;
    my @ret;

    ELEMENT: for (@$aref) {
      for my $re (@_) {
        push(@{ $ret[$pos{$re}] }, $_), next ELEMENT if $_ =~ $re;
      }
      push @{ $ret[$i] }, $_;
    }

    return map @$_, @ret;
  }

Then I thought I could beef it up with eval (I was wrong).

Then someone tried using grep, but they made it rather inefficiently:

  grep(/ALPHA/, @list), grep(/BETA/,@list), grep(!/ALPHA|BETA/,@list)

I pointed out it goes through the WHOLE list each time, so I offered this:

  sub grep_sift {
    my @sifted = ();
    my @list = @{ shift() };

    for my $re (@_) {
      my @normal;
      push @sifted, grep {
        ($_ =~ $re) ? 1 : do { push(@normal, $_), 0 }
      } @list;
      @list = @normal;
    }

    return (@sifted,@list);
  }

The results of benchmarks and code are at:

  http://www.pobox.com/~japhy/DALnet-perl/

-- 
MIDN 4/C PINYAN, NROTCURPI, US Naval Reserve             japhy@pobox.com
http://www.pobox.com/~japhy/                  http://pinyaj.stu.rpi.edu/
PerlMonth - An Online Perl Magazine            http://www.perlmonth.com/
The Perl Archive - Articles, Forums, etc.    http://www.perlarchive.com/


==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe