[24463] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 6646 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Wed Jun 2 14:11:49 2004

Date: Wed, 2 Jun 2004 11:10:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Wed, 2 Jun 2004     Volume: 10 Number: 6646

Today's topics:
        sorting and resorting hash (Andrea Spitaleri)
    Re: sorting and resorting hash <ittyspam@yahoo.com>
    Re: sorting and resorting hash <usenet@morrow.me.uk>
    Re: sorting and resorting hash <usenet@morrow.me.uk>
    Re: sorting and resorting hash <ittyspam@yahoo.com>
    Re: sorting and resorting hash <nobull@mail.com>
    Re: SSL connection to oracle using DBI? <Juha.Laiho@iki.fi>
        Unexpected subroutine behaviour without & (Kevin Collins)
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: 2 Jun 2004 09:02:06 -0700
From: spiritelllo@interfree.it (Andrea Spitaleri)
Subject: sorting and resorting hash
Message-Id: <4de1519a.0406020802.4a977ced@posting.google.com>

Hi,
the below code works great but I would like to receive some comment
about its perl-ish style. (I am not new posting this kind of messagge,
but I want improve my style) :-)
the problem is: I have several file, which they need to be ranked.
i.e.:
1.sft contains rms 1
2.sft contains rms 3
3.sft contains rms 2
4.sft contains rms 0.5
5.sft contains rms 3
 .......
and I would like to get at the end symbolic link, ranking the file bye
rms values:
rank_1.sft ---> 4.sft
rank_2.sft ---> 1.sft
rank_3.sft ---> 3.sft
rank_4.sft ---> 2.sft
rank_5.sft ---> 5.sft
 ........
#!/usr/bin/perl

use warnings;
foreach my $index (1 .. $ARGV[0]){
    open (FILE,"<$index.sft") || die "cannot open $index.sft : $!";
    while($line=<FILE>) {
	chomp $line;
	if($line=~/^rms/){
	    @info=split(/ /,$line);
	    push @rms,$index,$info[1];
	    %rms = @rms;  
	}
    }
}
print "@rms\n";
print "file ==> value rms\n";
sub tmp {
   $rms{$a}<=>$rms{$b};
} 
foreach $key (sort tmp (keys (%rms))){
#    print "$rms[$key] --> $key.sft -->> $rms{$key}\n";
    print "$key.sft -->> $rms{$key}\n";
    push @new,$key;
}
for ($i=1;$i<=$#new+1;++$i){
    print "$i\_rank -->> $new[$i-1].sft\n";
    system ("ln -s $new[$i-1].sft $i\_rank.sft");

}

# thanks
# regards
# xspirix


------------------------------

Date: Wed, 2 Jun 2004 12:57:35 -0400
From: Paul Lalli <ittyspam@yahoo.com>
Subject: Re: sorting and resorting hash
Message-Id: <20040602123732.Q8971@dishwasher.cs.rpi.edu>

On Wed, 2 Jun 2004, Andrea Spitaleri wrote:

> Hi,
> the below code works great but I would like to receive some comment
> about its perl-ish style. (I am not new posting this kind of messagge,
> but I want improve my style) :-)
> the problem is: I have several file, which they need to be ranked.
> i.e.:
> 1.sft contains rms 1
> 2.sft contains rms 3
> 3.sft contains rms 2
> 4.sft contains rms 0.5
> 5.sft contains rms 3
> .......
> and I would like to get at the end symbolic link, ranking the file bye
> rms values:
> rank_1.sft ---> 4.sft
> rank_2.sft ---> 1.sft
> rank_3.sft ---> 3.sft
> rank_4.sft ---> 2.sft
> rank_5.sft ---> 5.sft
> ........
> #!/usr/bin/perl
>
> use warnings;
> foreach my $index (1 .. $ARGV[0]){
>     open (FILE,"<$index.sft") || die "cannot open $index.sft : $!";
>     while($line=<FILE>) {
> 	chomp $line;
> 	if($line=~/^rms/){
> 	    @info=split(/ /,$line);
> 	    push @rms,$index,$info[1];
> 	    %rms = @rms;
> 	}

First, you need to clarify something a little.  Does each file contain
at most one line that matches "rms"?  That seems to be what you're
implying with your code, so it's the assumption I'll make too.  I would
replace your whole if statment with this:

if ($line =~ /^rms\s+(.*)/){
	$rms{$index} = $1;
}

There's no reason to be adding values to an array if you're only using
that array to build a hash.  Just build the hash directly.  Plus this will
avoid needlessly creating the temporary @info as well as the reassigning
of the entire %rms hash each time through the loop.


>     }
> }
> print "@rms\n";
> print "file ==> value rms\n";
> sub tmp {
>    $rms{$a}<=>$rms{$b};
> }
> foreach $key (sort tmp (keys (%rms))){
> #    print "$rms[$key] --> $key.sft -->> $rms{$key}\n";
>     print "$key.sft -->> $rms{$key}\n";
>     push @new,$key;
> }
> for ($i=1;$i<=$#new+1;++$i){
>     print "$i\_rank -->> $new[$i-1].sft\n";
>     system ("ln -s $new[$i-1].sft $i\_rank.sft");
>
> }

Why are you creating a whole new array to just store the keys of the hash
that already exists, if you're just using that array to loop over the
keys?

[untested]
@sorted = sort tmp keys %rms;
foreach $key (@sorted) {
   print "$key.sft --> $rms{$key}\n";
}

my $i = 1;
foreach $key (@sorted){
   print "${i}_rank --> $key.sft\n";
   system ("ln -s $key.sft ${i}_rank.sft");
   $i++;
}

The "${i}" method is the standard way of setting apart the variable name
from anything else in the string, rather than backslashing the following
character.

On another note, the expression $i<=$#new+1 is ugly.  Much preferred (if
you want to insist on a C-style loop, rather than a foreach loop - see
another recent thread in this newsgroup) would be $i <= @new

Paul Lalli



------------------------------

Date: Wed, 2 Jun 2004 17:02:19 +0000 (UTC)
From: Ben Morrow <usenet@morrow.me.uk>
Subject: Re: sorting and resorting hash
Message-Id: <c9l16r$pjg$1@wisteria.csv.warwick.ac.uk>


Quoth spiritelllo@interfree.it (Andrea Spitaleri):
> Hi,
> the below code works great but I would like to receive some comment
> about its perl-ish style. (I am not new posting this kind of messagge,
> but I want improve my style) :-)
> the problem is: I have several file, which they need to be ranked.
> i.e.:
> 1.sft contains rms 1
> 2.sft contains rms 3
> 3.sft contains rms 2
> 4.sft contains rms 0.5
> 5.sft contains rms 3
> .......
> and I would like to get at the end symbolic link, ranking the file bye
> rms values:
> rank_1.sft ---> 4.sft
> rank_2.sft ---> 1.sft
> rank_3.sft ---> 3.sft
> rank_4.sft ---> 2.sft
> rank_5.sft ---> 5.sft
> ........
> #!/usr/bin/perl
> 
> use warnings;

use strict;

my (@rms, %rms);

> foreach my $index (1 .. $ARGV[0]){

It is perhaps not terribly 'Perlish' to use 'foreach' as 'for' will do.

>     open (FILE,"<$index.sft") || die "cannot open $index.sft : $!";

open my $FILE, '<', "$index.sft" or die "...";

This FH will then close at the end of the scope (as written, your code
didn't close the last FH till the end of the script).

>     while($line=<FILE>) {

while (<$FILE>) {

> 	chomp $line;
> 	if($line=~/^rms/){

chomp;

But there's no need to as you split the line anyway.

if (/^rms/) {

etc.

> 	    @info=split(/ /,$line);
           ^^ my

> 	    push @rms,$index,$info[1];
> 	    %rms = @rms;

Why are you doing this? Why not just use %rms? Anyway, why do you make
the assignment every time through the loop? Try:

$rms{$index} = (split)[1];

or, since your keys are numeric and contiguous:

push @rms, (split)[1];

> 	}
>     }
> }
> print "@rms\n";
> print "file ==> value rms\n";

$\ = "\n";
print @rms;
print "file ==> value rms";

Or what I'd actually do is add '-l' to the #! line.

> sub tmp {
>    $rms{$a}<=>$rms{$b};
> } 
> foreach $key (sort tmp (keys (%rms))){

There's no need for a named sub:

for my $key (sort { $rms{$a} <=> $rms{b} } keys %rms) {

> #    print "$rms[$key] --> $key.sft -->> $rms{$key}\n";
>     print "$key.sft -->> $rms{$key}\n";
>     push @new,$key;
> }
> for ($i=1;$i<=$#new+1;++$i){

This is never necessary.

for my $i (0..$#new) {

(obviously you now have $i values one less than before...)

>     print "$i\_rank -->> $new[$i-1].sft\n";
>     system ("ln -s $new[$i-1].sft $i\_rank.sft");

There's no need to use system: perl has a symlink function.

I think you have your data structure backwards. I would use a hash the
other way round:

#!/usr/bin/perl -l

use warnings;
use strict;

my %rms;
$/ = undef;

for my $sft (1..$ARGV[0]) {
    $sft .= '.sft';
    open my $FILE, '<', $sft or die "can't open $sft: $!";
    <$FILE> =~ /^rms (\S+)/m and $rms{$1} = $sft;    
}

my $i;
for (sort keys %rms) {
    my $sym = ++$i . '_rank.sft';
    print "create symlink $sym -> $rms{$_} (rms: $_)";
    symlink $rms{$_}, $sym or die "symlink failed: $!";
}

__END__

Ben
    
-- 
"If a book is worth reading when you are six,                * ben@morrow.me.uk
it is worth reading when you are sixty." - C.S.Lewis


------------------------------

Date: Wed, 2 Jun 2004 17:07:07 +0000 (UTC)
From: Ben Morrow <usenet@morrow.me.uk>
Subject: Re: sorting and resorting hash
Message-Id: <c9l1fr$pjg$2@wisteria.csv.warwick.ac.uk>


Quoth Paul Lalli <ittyspam@yahoo.com>:
> On another note, the expression $i<=$#new+1 is ugly.  Much preferred (if
> you want to insist on a C-style loop, rather than a foreach loop - see
> another recent thread in this newsgroup) would be $i <= @new

I have to disagree here :). $#new is an ordinal, @new is a cardinal:
comparing an index to @new isn't right. A *much* better solution is, if
you're going to iterate over ordinals, iterate over ordinals:

for my $i (0..$#new) {

(or, for the pedantic,

for my $i ($[ .. $#new) {

:)

Ben

-- 
"The Earth is degenerating these days. Bribery and corruption abound.
Children no longer mind their parents, every man wants to write a book,
and it is evident that the end of the world is fast approaching."
     -Assyrian stone tablet, c.2800 BC                         ben@morrow.me.uk


------------------------------

Date: Wed, 2 Jun 2004 13:13:11 -0400
From: Paul Lalli <ittyspam@yahoo.com>
Subject: Re: sorting and resorting hash
Message-Id: <20040602131048.J8971@dishwasher.cs.rpi.edu>

On Wed, 2 Jun 2004, Ben Morrow wrote:

> Quoth Paul Lalli <ittyspam@yahoo.com>:
> > On another note, the expression $i<=$#new+1 is ugly.  Much preferred (if
> > you want to insist on a C-style loop, rather than a foreach loop - see
> > another recent thread in this newsgroup) would be $i <= @new
>
> I have to disagree here :). $#new is an ordinal, @new is a cardinal:
> comparing an index to @new isn't right. A *much* better solution is, if
> you're going to iterate over ordinals, iterate over ordinals:
>
> for my $i (0..$#new) {
>
> (or, for the pedantic,
>
> for my $i ($[ .. $#new) {

TMTOWTDI, of course.  I just can't see typing $#new+1 when @new does just
as well, and is (at least to me) just as readable, if not more.

Now, on the other hand, had the OP actually had a foreach-style loop,
starting at 0, as you suggested, I surely would have recommended $#new as
opposed to @new-1.

Paul Lalli


------------------------------

Date: 02 Jun 2004 18:22:01 +0100
From: Brian McCauley <nobull@mail.com>
Subject: Re: sorting and resorting hash
Message-Id: <u9hdttg9ja.fsf@wcl-l.bham.ac.uk>

spiritelllo@interfree.it (Andrea Spitaleri) writes:

> the below code works great but I would like to receive some comment
> about its perl-ish style. (I am not new posting this kind of messagge,
> but I want improve my style) :-)


> #!/usr/bin/perl

use strict;
 
Putting this in your code will help you to find all the places you've
forgotten to put my.

> use warnings;
> foreach my $index (1 .. $ARGV[0]){
>     open (FILE,"<$index.sft") || die "cannot open $index.sft : $!";
>     while($line=<FILE>) {
           ^^
Missing my.        

> 	chomp $line;
> 	if($line=~/^rms/){
> 	    @info=split(/ /,$line);
           ^^
Missing my.

Why use an array if you only want one value?

> 	    push @rms,$index,$info[1];
> 	    %rms = @rms;  

Why does @rms exist?

Why not just say:

  $rms{$index} = $info[1];

> 	}
>     }
> }
> print "@rms\n";
> print "file ==> value rms\n";
> sub tmp {
>    $rms{$a}<=>$rms{$b};
> } 

tmp is a bad name for a subroutine.

Actually there's no need to make this subroutine at all.

> foreach $key (sort tmp (keys (%rms))){
         ^^
Missing my.

> #    print "$rms[$key] --> $key.sft -->> $rms{$key}\n";
>     print "$key.sft -->> $rms{$key}\n";
>     push @new,$key;
> }

Why not just:

  my @new = sort { $rms{$a}<=>$rms{$b} } keys (%rms);

but as I said abouve you shouldn't use a hash at all.

> for ($i=1;$i<=$#new+1;++$i){
      ^^

Missing my.

More conventionally written.

for my $i ( 1 .. @new ) {

>     print "$i\_rank -->> $new[$i-1].sft\n";
>     system ("ln -s $new[$i-1].sft $i\_rank.sft");
> }

Use the builtin symlink() function rather than running an external
process.

All in all I think it can be a lot simpler:

#!/usr/bin/perl 
use strict;
use warnings;

my %rms;

foreach my $index (1 .. $ARGV[0]){
    open (FILE,"<$index.sft") or die "cannot open $index.sft : $!";
    while(my $line = <FILE>) {
	$rms{$index} = $1 if $line =~ /^rms (.*)/;
    }
}

my $rank;
for my $index ( sort { $rms{$a} <=> $rms{$b} } keys %rms ){
    $rank++;
    print "$rank\_rank -->> $index.sft\n";
    symlink("$index.sft","$rank\_rank.sft") or warn $!; 
}


-- 
     \\   ( )
  .  _\\__[oo
 .__/  \\ /\@
 .  l___\\
  # ll  l\\
 ###LL  LL\\


------------------------------

Date: Wed, 02 Jun 2004 16:17:03 GMT
From: Juha Laiho <Juha.Laiho@iki.fi>
Subject: Re: SSL connection to oracle using DBI?
Message-Id: <c9ku8u$6fq$1@ichaos.ichaos-int>

Joe User <william.bathurst@nospam.com> said:
>Has anyone done this before? If so, please let me know. Just
>remove the "nospam" and put in oracle in my email. Or, just reply
>to my post.

Note that if you're using Oracle MTS (multithreaded server)
functionality, this'll become difficult (I'm not certain if
impossible, but difficult at least). Without MTS (so, with
traditional dedicated-server setup) this might be doable with
stunnel, as described in another response.
-- 
Wolf  a.k.a.  Juha Laiho     Espoo, Finland
(GC 3.0) GIT d- s+: a C++ ULSH++++$ P++@ L+++ E- W+$@ N++ !K w !O !M V
         PS(+) PE Y+ PGP(+) t- 5 !X R !tv b+ !DI D G e+ h---- r+++ y++++
"...cancel my subscription to the resurrection!" (Jim Morrison)


------------------------------

Date: Wed, 02 Jun 2004 17:20:42 GMT
From: spamtotrash@toomuchfiction.com (Kevin Collins)
Subject: Unexpected subroutine behaviour without &
Message-Id: <slrncbs335.93b.spamtotrash@doom.unix-guy.com>

Hi,

	I've just stumbled across a strange problem on my HP-UX systems. The
following code will demonstrate the problem:

#!/usr/bin/perl -w

use strict;
use warnings;

my @list = qw(cc aa bb aa dd zz ee);
print join(" ", sort(UniqArray(@list))) . "\n";
print join(" ", sort(&UniqArray(@list))) . "\n";

sub UniqArray
{
    # This function takes an array reference and returns
    # an array without dups
    
    # local variables
    my %tmp;
    my @returns;

    foreach (@list)
    {
        # if the hash element has a value, then don't
        # add it to return list since we've already added it
        push (@returns, $_) unless ($tmp{$_});
        $tmp{$_}++;
    }

    return @returns;
}

I have two different "home built" versions of Perl (5.6.1 and 5.8.0) and two
HP-supplied versions (5.6.1 and 5.8.0).

The output I would expect:

aa bb cc dd ee zz
aa bb cc dd ee zz

However, here is what I see:

Custom 5.6.1:

ee zz dd aa bb aa cc
aa bb cc dd ee zz

Custom 5.8.0:

ee zz dd aa bb aa cc
aa bb cc dd ee zz

HP's 5.6.1:

ee zz dd aa bb aa cc
aa bb cc dd ee zz

HP's 5.8.0:

aa bb cc dd ee zz
aa bb cc dd ee zz

I also checked Perl 5.8.0 on RedHat 9.0 and see my expected results. I'm
wondering why I need to call &UniqArray(@list) instead of UniqArray(@list)? I
started looking into this when a new script was not giving me a correctly
sorted list. Is there some know issue with this? 

Thanks,

Kevin


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 6646
***************************************


home help back first fref pref prev next nref lref last post