Click here to get back home

Accomodate for poor db design using Sort::Maker?

 HomeNewsGroups | Search | About
 comp.lang.perl.modules    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
Accomodate for poor db design using Sort::Maker? DJ Stunks 12-09-2006
Posted by DJ Stunks on December 10, 2006, 12:22 pm
Please log in for more thread options


harryfmudd [AT] comcast [DOT] net wrote:
> John W. Krahn wrote:
> > DJ Stunks wrote:
> >>for each row I'd like to return the column
> >>numbers which have the highest number of counts, and the highest column
> >>number with any counts at all. I refer to these values as mode and max
> >>respectively
> >>
> >> print "id\tmode\tmax\n";
> >> while ( my $hashref = fetchrow_hashref() ) {
> >>         my $id = $hashref->;
> >>
> >>         # mode = col number with greatest count
> >>         my $mode = ( map { $_->[0] }
> >>          sort { $b->[1] <=> $a->[1] }
> >>          map { [ $_, $hashref-> ] } 1..5 )[0];
> >>
> >>         # max = highest col number with any count
> >>         my $max = ( sort { $b <=> $a }
> >>          map { $_ if $hashref-> > 0 } 1..5 )[0];
> >>
> >>         $max = 1 if $max eq ''; #all zeros
> >
> >
> >
> > If you want efficiency then you should just use loops instead of sorting:
> >
> >
> > my ( $mode, $curr ) = ( 1, 0 );
> > for ( 1 .. 5 ) {
> > if ( $hashref->{ "col$_" } > $curr ) {
> > $curr = $hashref->{ "col$_" };
> > $mode = $_;
> > }
> > }
> >
> > my $max = 1;
> > for ( reverse 1 .. 5 ) {
> > if ( $hashref->{ "col$_" } > 0 ) {
> > $max = $_;
> > last;
> > }
> > }
> >
>
> Have you looked at List::Util? It's a standard module in Perl 5.8, and
> contains a max function. So the first loop becomes something like
>
> use List::Util qw;
>
> my $mode = max (map } 1..5);
>
> Assuming the only zeros are trailing, the second loop could be
>
> my $max = grep {$_ > 0} map } 1..5

I appreciate the input, I don't think I was clear enough about what I
was looking for. The counts themselves don't really matter, what I was
looking for was the column numbers associated with 1) highest count
($mode); and 2) the highest column number with any count at all ($max).

John's solution worked well. I was only thinking of sort() because I
wanted largest of one thing with respect to another thing. I couldn't
think of a way to get max() to operate like that without going through
all the columns twice (once to find the max, and a second time to find
which column it was associated with).

Thanks,
-jp


Posted by DJ Stunks on December 10, 2006, 12:15 pm
Please log in for more thread options


John W. Krahn wrote:
> DJ Stunks wrote:
> > for each row I'd like to return the column
> > numbers which have the highest number of counts, and the highest column
> > number with any counts at all. I refer to these values as mode and max
> > respectively

> > print "id\tmode\tmax\n";
> > while ( my $hashref = fetchrow_hashref() ) {
> >         my $id = $hashref->;
> >
> >         # mode = col number with greatest count
> >         my $mode = ( map { $_->[0] }
> >          sort { $b->[1] <=> $a->[1] }
> >          map { [ $_, $hashref-> ] } 1..5 )[0];
> >
> >         # max = highest col number with any count
> >         my $max = ( sort { $b <=> $a }
> >          map { $_ if $hashref-> > 0 } 1..5 )[0];
> >
> >         $max = 1 if $max eq ''; #all zeros
>
>
> If you want efficiency then you should just use loops instead of sorting:
>
>
> my ( $mode, $curr ) = ( 1, 0 );
> for ( 1 .. 5 ) {
> if ( $hashref->{ "col$_" } > $curr ) {
> $curr = $hashref->{ "col$_" };
> $mode = $_;
> }
> }
>
> my $max = 1;
> for ( reverse 1 .. 5 ) {
> if ( $hashref->{ "col$_" } > 0 ) {
> $max = $_;
> last;
> }
> }

Thanks John, I knew something was nagging me about my approach, but
once you're in a mindset sometimes it's hard to break out. Your right
of course, why sort all the elements when I'm only interested in one.

I altered your two loops to return both numbers in one loop (in
actuality there are 60 columns, not just 5, and the $mode and $max
usually occur below 30):

        my ( $max, $mode, $curr ) = ( 1,1,0 );
        for my $i ( 1 .. 5 ) {
                my $count = $hashref->;

                if ( $count > $curr ) {
                        $curr = $count;
                        $mode = $i;
                }
                
                if ( $count > 0 ) {
                        $max = $i;
                }
        }

Thanks again,
-jp


Similar ThreadsPosted
ANNOUNCE: Sort::Maker .02 September 2, 2004, 5:09 am
Sort::Maker : anonymous sub is compiled outside of my module December 5, 2006, 8:25 am
Sort::Maker: style => 'plain' difficulty December 14, 2006, 4:35 am
Sort::Maker: (Notes) The plain and the orcish don't include the "init_code" December 14, 2006, 7:32 am
CGI scripts and modular design? September 28, 2004, 9:41 am
The Month in Perl Software Design: Review of January 2005 February 10, 2005, 10:39 pm
[ANN] Sort::Key 0.02 April 28, 2005, 11:02 am
Win32::OLE::Const 'Microsoft Excel' - sort & freeze pane April 30, 2008, 12:48 am

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap