[30979] in Perl-Users-Digest

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

Perl-Users Digest, Issue: 2224 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Feb 20 14:14:21 2009

Date: Fri, 20 Feb 2009 11:14:12 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Fri, 20 Feb 2009     Volume: 11 Number: 2224

Today's topics:
    Re: Sorting hash of hashes <justin.0810@purestblue.com>
    Re: Sorting hash of hashes <justin.0810@purestblue.com>
    Re: Sorting hash of hashes <justin.0810@purestblue.com>
    Re: Sorting hash of hashes <justin.0810@purestblue.com>
        weird matching variable behavior <juliani.moon@gmail.com>
    Re: weird matching variable behavior <tim@burlyhost.com>
    Re: weird matching variable behavior <rvtol+usenet@xs4all.nl>
    Re: weird matching variable behavior <thepoet_nospam@arcor.de>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

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

Date: Fri, 20 Feb 2009 13:50:48 -0000
From: Justin C <justin.0810@purestblue.com>
Subject: Re: Sorting hash of hashes
Message-Id: <481e.499eb538.4f75b@zem>

On 2009-02-19, Greg Bacon <gbacon@hiwaay.net> wrote:
> It looks like you must have called Dumper(%hashes). What you really
> want is Dumper(\%hashes) -- note the backslash -- so you can later
> evaluate the dump to create an equivalent hash.

I copied that output from a web-browser, it doesn't appear much
different using what you suggest, only the $VAR2,  $VAR3 etc are
missing.


> Note that %hashes is a really bad name.

Oh, I know! I didn't spend enough time thinking this all through before
I got coding.


> You described your structure with
>
>     $hashes{$report}{$line}{$colNumber}
>
> so %report is probably a better name. (I assume stk1324r2 is a
> report code.)
>
> You can sort and print the descriptions with
>
>     print map "$_\n",
>           sort
>           map { my $r = $report{$_};
>                 map ref $r->{$_} && $r->{$_}{2} ? $r->{$_}{2} : (),
>                     keys %$r;
>               }
>           keys %report;
>
> I don't recommend this approach, but it's instructive. Read it
> bottom-to-top:
>
>     1. For each possible report code (keys %report)
>     2. Make note of where we are in the hash ($r = $report{$_})
>     3. Make sure it's a report code (ref $r->{$_} && $r->{$_}{2})
>     4. Extract the description from column 2.

I've seen 'map' used a few times before, it's not a command I'm familiar
with. I'll read the documentation before I do any more work on this.


> You can make it a little nicer if you can infer from the key that
> its value is a report (say, if it starts with "stk"):
>
>     print map "$_\n",
>           sort
>           map { my $r = $report{$_}; map $r->{$_}{2}, keys %$r; }
>           grep /^stk/,
>           keys %report;
>
> I take it you want more than the descriptions, though. Do you also
> need the "paths" to get to them?
>
> Hope this helps,
> Greg

It's given me stuff to think about, and some help, yes. Thank you.


	Justin.

-- 
Justin C, by the sea.


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

Date: Fri, 20 Feb 2009 13:56:18 -0000
From: Justin C <justin.0810@purestblue.com>
Subject: Re: Sorting hash of hashes
Message-Id: <4863.499eb682.b9a0a@zem>

On 2009-02-19, Greg Bacon <gbacon@hiwaay.net> wrote:
>: I take it you want more than the descriptions, though. Do you also
>: need the "paths" to get to them?
>
> If that's the approach you're after, use code similar to the following:
>
>     my $DESC_COLUMN = 2;
>
>     sub item_paths {
>       my($report) = @_;
>
>       my @descs;
>
>       foreach my $code (keys %$report) {
>         next unless $code =~ /^stk/ && ref $report->{$code};
>
>         foreach my $line (keys %{ $report->{$code} }) {
>           push @descs => [ $code, $line ]
>             if exists $report->{$code}{$line}{$DESC_COLUMN};
>         }
>       }
>
>       @descs;
>     }
>
>     print map "$_\n",
>           sort
>           map $report{ $_->[0] }{ $_->[1] }{ $DESC_COLUMN },
>           item_paths \%report;

More to think about, thank you. I'm considering an alteration to my data
structure (%hashes), with each report getting it's own hash, named at
run-time from the report code. Seems a better way to me. It'll reduce
the 'depth' of the hash for a start. I'm just going through the replies
I've received to my post before I read perldoc -f map, so I'll keep this
to re-read after I've read the docs. Thanks for you help.

	Justin.

-- 
Justin C, by the sea.


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

Date: Fri, 20 Feb 2009 14:00:17 -0000
From: Justin C <justin.0810@purestblue.com>
Subject: Re: Sorting hash of hashes
Message-Id: <4888.499eb771.59c06@zem>

On 2009-02-19, J. Gleixner <glex_no-spam@qwest-spam-no.invalid> wrote:
> Justin C wrote:
>> On 2009-02-19, Justin C <justin.0810@purestblue.com> wrote:
>>> Here's how my hash looks:
>>>
>>> $hashes{$report}{$line}{$colNumber}
>>>
>>> So, in %hashes, is data from several reports, grouped by report, then
>>> line (well, stock code, which is the first field on the line), the
>>> column number. Here is a little of the output of Data::Dumper:
>>>
[snip]
>
> One way would be to go through all of your data, storing the field
> you're after as a key, provided they're all unique, and maybe the
> hash of data as the value.

I can't garuantee that the descriptions will be unique. But thanks
anyway.


> Having keys like 1,2,3, etc. is not very descriptive and after a few
> months, when you look at your code again, you'll wish you used
> something that made sense.

I have, within the code, described the construction, and the numbers are
the column numbers within the report, so it's not overly confusing.

	Justin.

-- 
Justin C, by the sea.


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

Date: Fri, 20 Feb 2009 14:20:12 -0000
From: Justin C <justin.0810@purestblue.com>
Subject: Re: Sorting hash of hashes
Message-Id: <4d39.499ebc1c.184ad@zem>

On 2009-02-19, xhoster@gmail.com <xhoster@gmail.com> wrote:
> justin.news@purestblue.com wrote:
>> On 2009-02-19, Justin C <justin.0810@purestblue.com> wrote:
>> > Here's how my hash looks:
>> >
>> > $hashes{$report}{$line}{$colNumber}
>> >
>> > So, in %hashes, is data from several reports, grouped by report, then
>> > line (well, stock code, which is the first field on the line), the
>> > column number. Here is a little of the output of Data::Dumper:
>> >
>> > $VAR1 = 'types';
>> > $VAR2 = {
>> >           'BE' => 1
>> >         };
>> > $VAR3 = 'stk1324r2';
>> > $VAR4 = {
>
> ...
>
> You should give Dumper a reference to your hash, not the flattened list
> of your hash.  Then there would be only one $VARx and it reflect the true
> structure you have.

Yes, others have said similar. It does look clearer that way. I have
made a note for next time.


>> I've looked further at this and found a "sort hash by value" example.
>> Looking at it, I remember it from the Llama. I can see how to apply that
>> to a simple hash, "@sorted = sort { $hash{$a} cmp $hash{$b} } keys
>> %hash". But am not sure how to make $hashes{$report}{$item}{2} fit.
>>
>> What I've got is:
>>
>> my @sorted = sort byAlpha ( keys ( %{$hashes{$report}} ) );
>>
>> sub byAlpha {
>>     $hashes{$report}{$item}{2}{a} cmp $hashes{$report}{$item}{2}{a};
>> }
>
> What is the last {a} for?  You don't have such a critter in your data dump,
> the value associated with key 2 is a string, not a hashref with 'a' as a
> key.

Typo, I was going for, more or less,  { $a cmp $b } but managed to type
$a both times.



> It seems like it should be
>  $hashes{$report}{$a}{2} cmp $hashes{$report}{$b}{2};
>
>> And, of course, $report is not passed to the sub and is therefore undef,
>> and perl, rightly, complains. And at this point I'm stumped... again.
>
> Don't use a named subroutine as the sort's code block, just put the code
> directly into the sort block.  That way it executes in the context of
> the sort, where $report is defined.

That all makes perfect sense, but I'm having difficulty today making
things work.

 .
 .
 .
Nope, just a hard of understanding day. Got it now with:

my @sorted = sort { $hashes{$report}{$a}{2} cmp $hashes{$report}{$b}{2}
} keys %{$hashes{$report}}

Great stuff. Thank you for your help.


	Justin.

-- 
Justin C, by the sea.


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

Date: Fri, 20 Feb 2009 09:23:31 -0800 (PST)
From: "juliani.moon@gmail.com" <juliani.moon@gmail.com>
Subject: weird matching variable behavior
Message-Id: <223729cb-b714-495e-8f5f-5dde7a23fb48@r41g2000yqm.googlegroups.com>

I am using perl v5.8.5.

I made a simple construct to make email addresses hyper-linkable:
 if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
      s!$1!<a href="mailto:$1">$1</a>!g;
 }
However it only effectively takes out the email address, as if only
the first "$1" matched and the "$1" at the 2nd and 3rd places becomes
empty because it replaces an email address only with:
  <a href="mailto:"></a>

Then I tried to use "$&" in places of "$1", as in:
 if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
      s!$&!<a href="mailto:$&">$&</a>!g;
 }
This time the email addresses are found and replaced with html codes
like:
<a href="mailto: username@somedomain.com "> username@somedomain.com </
a>
-- but "$&" carries a space on both sides of the email address.

It seems trivial and unnecessary although I can work around by this:
  if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
      $emem = $1;
      s!$emem!<a href="mailto:$emem">$emem</a>!g;
  }
My wonders are (1) I saw examples where "$1" was used as in my first
example. Why it fails to work as in my first example? (2) Is it by
default that "$&" carries spaces on both sides of its content?
(To"clean" it, I would have to introduce a new variable as "$&" is a
"read-only value"). Things shouldn't be that complicated, are they?

Joe


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

Date: Fri, 20 Feb 2009 09:40:07 -0800
From: Tim Greer <tim@burlyhost.com>
Subject: Re: weird matching variable behavior
Message-Id: <XVBnl.13842$EO2.10592@newsfe04.iad>

juliani.moon@gmail.com wrote:

> I am using perl v5.8.5.
> 
> I made a simple construct to make email addresses hyper-linkable:
>  if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
>       s!$1!<a href="mailto:$1">$1</a>!g;
>  }
> However it only effectively takes out the email address, as if only
> the first "$1" matched and the "$1" at the 2nd and 3rd places becomes
> empty because it replaces an email address only with:
>   <a href="mailto:"></a>

The above logic won't work.

I assume you meant something like (albeit this isn't a good
solution/example):
s/\b([a-zA-Z\.]+\@[a-zA-Z\.]+)\b/<a href="mailto:$1">$1<\/a>/g;

Are you sure there are white spaces at the start and end of the email
addresses in that string?

Do you assume the email addresses won't have any numbers (digits)
anywhere?

Just so you're aware, the above will match invalid email addresses, and
not match valid one's.
-- 
Tim Greer, CEO/Founder/CTO, BurlyHost.com, Inc.
Shared Hosting, Reseller Hosting, Dedicated & Semi-Dedicated servers
and Custom Hosting.  24/7 support, 30 day guarantee, secure servers.
Industry's most experienced staff! -- Web Hosting With Muscle!


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

Date: Fri, 20 Feb 2009 18:45:16 +0100
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: weird matching variable behavior
Message-Id: <499eec2c$0$191$e4fe514c@news.xs4all.nl>

juliani.moon@gmail.com wrote:

> I am using perl v5.8.5.
> 
> I made a simple construct to make email addresses hyper-linkable:
>  if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
>       s!$1!<a href="mailto:$1">$1</a>!g;
>  }

perldoc -f split
perldoc -f join

-- 
Ruud


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

Date: Fri, 20 Feb 2009 18:51:11 +0100
From: Christian Winter <thepoet_nospam@arcor.de>
Subject: Re: weird matching variable behavior
Message-Id: <499eed5d$0$32679$9b4e6d93@newsspool2.arcor-online.net>

juliani.moon@gmail.com schrieb:
> I am using perl v5.8.5.
> 
> I made a simple construct to make email addresses hyper-linkable:
>  if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
>       s!$1!<a href="mailto:$1">$1</a>!g;
>  }

Your making things overly difficult for yourself by the
unneccessary if(). When the pattern doesn't match, it
doesn't replace, so no need to put a conditional around it.
(just as a side note, as I don't know whether this applies
to your script, digits and the dash are also allowed in
mail addresses)

> However it only effectively takes out the email address, as if only
> the first "$1" matched and the "$1" at the 2nd and 3rd places becomes
> empty because it replaces an email address only with:
>   <a href="mailto:"></a>

That's correct behaviour, because $1 is the first matching
parenthesis from the _last successfull pattern match_, in
your case, it's still valid in the matching part of the
expression, but when the replacement expression
gets evaluated, the last successfull match was the one
currently performed, which didn't capture anything.

> Then I tried to use "$&" in places of "$1", as in:
>  if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
>       s!$&!<a href="mailto:$&">$&</a>!g;
>  }
> This time the email addresses are found and replaced with html codes
> like:
> <a href="mailto: username@somedomain.com "> username@somedomain.com </
> a>
> -- but "$&" carries a space on both sides of the email address.

Yes, because $& contains the whole expression, not just the part
within the capture.

> It seems trivial and unnecessary although I can work around by this:
>   if ($_ =~ / ([a-zA-Z\.]+\@[a-zA-Z\.]+) /g) {
>       $emem = $1;
>       s!$emem!<a href="mailto:$emem">$emem</a>!g;
>   }
> My wonders are (1) I saw examples where "$1" was used as in my first
> example. Why it fails to work as in my first example?

You misread the examples. They were just looking similar.

> (2) Is it by
> default that "$&" carries spaces on both sides of its content?
> (To"clean" it, I would have to introduce a new variable as "$&" is a
> "read-only value").

No it isn't, as explained above. If you match whitespace in your
pattern, it will also be present in $&.

> Things shouldn't be that complicated, are they?

Nope, they're actually straight forward, once you get a hang on it.

s#([a-zA-Z.-]+\@[a-zA-Z.-]+)#<a href="mailto:$1">$1</a>#g;
should do fine without any if()s and while()s.

-Chris


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

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 V11 Issue 2224
***************************************


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