Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > [Newbie] Stupid problem need simple answer (Array & RegExp)

Reply
Thread Tools

[Newbie] Stupid problem need simple answer (Array & RegExp)

 
 
Daedalus
Guest
Posts: n/a
 
      06-24-2004
Keep in mind that I'm fresh one week years-old Perl newbie... thanks
I just need some information about what happen when :

my @string_list; #lets say that this array contain a couple of string, 3:
(the street, a book, theater)

foreach my $string (@string_list){
if ($string =~ s/(^the\b)|(^a\b)|//i){
$string_list[++$#string_lis] = $string
}
}

When I write: if ($string =~ s/(^the\b)|(^a\b)|//i)..., do I actually
replacing the string within @string_list (since $string is passed by
"foreach" from one of the string of @string_list) I'm asking cause I thought
that it would add the new strings to the array without touching what was
already there. So I would end with this list as @string_list (the street, a
book, theater, street, book).
But when try this, it overwrite and add. So it gives me ( street, book,
theater, street, book).
What am I doing wrong?

Thanks
DAE


 
Reply With Quote
 
 
 
 
Daedalus
Guest
Posts: n/a
 
      06-24-2004
Well I think I was guessing right cause if I write this instead:

foreach (@string_list){
my $string = $_;
if ($string =~ s/(^the\b)|(^a\b)//i){
$string_list[++$#string_lis] = $string
}
}
I get the wanted result, but I would like someone to confirm that.

thanks
DAE


"Daedalus" <(E-Mail Removed)> a écrit dans le message de news:
BsvCc.530$(E-Mail Removed)...
> Keep in mind that I'm fresh one week years-old Perl newbie... thanks
> I just need some information about what happen when :
>
> my @string_list; #lets say that this array contain a couple of string,

3:
> (the street, a book, theater)
>
> foreach my $string (@string_list){
> if ($string =~ s/(^the\b)|(^a\b)//i){
> $string_list[++$#string_lis] = $string
> }
> }
>
> When I write: if ($string =~ s/(^the\b)|(^a\b)|//i)..., do I actually
> replacing the string within @string_list (since $string is passed by
> "foreach" from one of the string of @string_list) I'm asking cause I

thought
> that it would add the new strings to the array without touching what was
> already there. So I would end with this list as @string_list (the street,

a
> book, theater, street, book).
> But when try this, it overwrite and add. So it gives me ( street, book,
> theater, street, book).
> What am I doing wrong?
>
> Thanks
> DAE
>
>



 
Reply With Quote
 
 
 
 
Joe Smith
Guest
Posts: n/a
 
      06-24-2004
Daedalus wrote:

> Keep in mind that I'm fresh one week years-old Perl newbie... thanks
> I just need some information about what happen when :
>
> my @string_list; #lets say that this array contain a couple of string, 3:
> qw(the street, a book, theater);
>
> foreach my $string (@string_list){
> if ($string =~ s/(^the\b)|(^a\b)|//i){
> $string_list[++$#string_lis] = $string
> }
> }
>
> When I write: if ($string =~ s/(^the\b)|(^a\b)|//i)..., do I actually
> replacing the string within @string_list (since $string is passed by
> "foreach" from one of the string of @string_list)


Yes. You are modifying the array element as they are being processed
since the foreach variable is aliased to the array element and not
a copy of the array element.

The line inside the if() is better written as
push @string_list, $string;

-Joe
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      06-24-2004
Daedalus <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> "Daedalus" <(E-Mail Removed)> a écrit dans le message de news:
> BsvCc.530$(E-Mail Removed)...


[top-post rearranged]

> > Keep in mind that I'm fresh one week years-old Perl newbie... thanks
> > I just need some information about what happen when :
> >
> > my @string_list; #lets say that this array contain a couple of string,

> 3:
> > (the street, a book, theater)
> >
> > foreach my $string (@string_list){
> > if ($string =~ s/(^the\b)|(^a\b)//i){
> > $string_list[++$#string_lis] = $string
> > }
> > }
> >
> > When I write: if ($string =~ s/(^the\b)|(^a\b)|//i)..., do I actually
> > replacing the string within @string_list (since $string is passed by
> > "foreach" from one of the string of @string_list) I'm asking cause I

> thought
> > that it would add the new strings to the array without touching what was
> > already there. So I would end with this list as @string_list (the street,

> a
> > book, theater, street, book).
> > But when try this, it overwrite and add. So it gives me ( street, book,
> > theater, street, book).
> > What am I doing wrong?

>
> Well I think I was guessing right cause if I write this instead:
>
> foreach (@string_list){
> my $string = $_;
> if ($string =~ s/(^the\b)|(^a\b)//i){


What are the capturing parentheses in the pattern for? s/^the\b|^a\b//i
does the same thing.

> $string_list[++$#string_lis] = $string

^^
Typo here. Don't re-type code, copy/paste it.

Also, "++$#string_list" would be better written as (scalar)
"@string_list".

> }
> }
> I get the wanted result, but I would like someone to confirm that.


Your code (in all variants) has another problem. You are not supposed
to change an array while running a for-loop over it. (See "foreach" in
perlsyn, I suppose.) That it appears to work in this instance doesn't
mean it will with other versions of Perl.

There are lots of ways to repair this, one is

push @string_list, map /(?:the\b|a\b)?\s*(.*)/i, @string_list;

Instead of deleting the unwanted part, this captures the wanted part.
I have also changed the regex so that it also catches trailing
whitespace with the articles.

Anno
 
Reply With Quote
 
Thomas Kratz
Guest
Posts: n/a
 
      06-24-2004
Anno Siegel wrote:

>
> Your code (in all variants) has another problem. You are not supposed
> to change an array while running a for-loop over it. (See "foreach" in
> perlsyn, I suppose.) That it appears to work in this instance doesn't
> mean it will with other versions of Perl.


AFAIK you are not supposed to change the array, but changing the aliased
elements should be ok.

so:

push(@array, $_) for @array # not recommended

s/A/B/g for @array # ok

Right?

Thomas

--
open STDIN,"<&DATA";$=+=14;$%=50;while($_=(seek( #J~.> a>n~>>e~.......>r.
STDIN,$:*$=+$,+$%,0),getc)){/\./&&last;/\w| /&&( #.u.t.^..oP..r.>h>a~.e..
print,$_=$~);/~/&&++$:;/\^/&&--$:;/>/&&++$,;/</ #.>s^~h<t< ..~. ...c.^..
&&--$,;$:%=4;$,%=23;$~=$_;++$i==1?++$,:_;}__END__#.... >>e>r^..>l^...>k^..
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      06-24-2004
Thomas Kratz <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Anno Siegel wrote:
>
> >
> > Your code (in all variants) has another problem. You are not supposed
> > to change an array while running a for-loop over it. (See "foreach" in
> > perlsyn, I suppose.) That it appears to work in this instance doesn't
> > mean it will with other versions of Perl.

>
> AFAIK you are not supposed to change the array, but changing the aliased
> elements should be ok.
>
> so:
>
> push(@array, $_) for @array # not recommended
>
> s/A/B/g for @array # ok
>
> Right?


Right.

Anno
 
Reply With Quote
 
Daedalus
Guest
Posts: n/a
 
      06-24-2004
> > if ($string =~ s/(^the\b)|(^a\b)//i){
>
> What are the capturing parentheses in the pattern for? s/^the\b|^a\b//i
> does the same thing.


Actually It was for precedence, I wasn't sure about this \b|^ thing , it
doesn't harm, doesn't it ?
I'll have to familiarize with regexp precedence.


> > $string_list[++$#string_lis] = $string

> ^^
> Typo here. Don't re-type code, copy/paste it.


Sorry I didn't know, but it makes sense to me now.

> Your code (in all variants) has another problem. You are not supposed
> to change an array while running a for-loop over it. (See "foreach" in
> perlsyn, I suppose.) That it appears to work in this instance doesn't
> mean it will with other versions of Perl.


Ok, about this, I wanted the foreach to look at the new string in the array
until there's nothing to add. So if the array start with one string like "to
the bookstore", and the the regexp is s/^to\b|^the\b//i, I would end with 3
string in the array: ("to the bookstore", "the bookstore", "bookstore"). I
need to extract all possible variants, so I don't want to process the array
only once and get rid of everything at the same time. There is probably a
better way to acheive this but that's the only one I found.


> There are lots of ways to repair this, one is
>
> push @string_list, map /(?:the\b|a\b)?\s*(.*)/i, @string_list;
>
> Instead of deleting the unwanted part, this captures the wanted part.
> I have also changed the regex so that it also catches trailing
> whitespace with the articles.


Thank for that. It doesn't act exactly like I want since it would remove "to
the" at the same time, but it just reminds me of that push operator wich I
could use instead of "$string_list[++$#string_lis]" and I just learn the map
operator wich would avoid to overwrite the original array. Well I'm learning
and I like it! But for now (with my little knowledge) i'm still stuck with
writing the array from inside the for foreach.


> Anno



 
Reply With Quote
 
Daedalus
Guest
Posts: n/a
 
      06-24-2004

"Anno Siegel" <(E-Mail Removed)-berlin.de> a écrit dans le message de
news: cbeg3h$gii$(E-Mail Removed)-Berlin.DE...
> Thomas Kratz <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > Anno Siegel wrote:
> >
> > >
> > > Your code (in all variants) has another problem. You are not supposed
> > > to change an array while running a for-loop over it. (See "foreach"

in
> > > perlsyn, I suppose.) That it appears to work in this instance doesn't
> > > mean it will with other versions of Perl.

> >
> > AFAIK you are not supposed to change the array, but changing the aliased
> > elements should be ok.
> >
> > so:
> >
> > push(@array, $_) for @array # not recommended
> >
> > s/A/B/g for @array # ok
> >
> > Right?

>
> Right.


Well the problem is that s///g don't do what I want, since it change every
thing at the same time.
Anyway (for now) it couldn't turn into an infinite loop, since the content
of the loop will inevitably stop adding to the array when it'll stop to find
matches (which is also inevitable, since even if all the words match, the
loop will end with an empty string)
I know it's not the perfect solution (and I'll try to find a better way
while i'm on my learning process), so if someone have any idea... I'd be
glad to correct this misuse.

DAE



 
Reply With Quote
 
Daedalus
Guest
Posts: n/a
 
      06-24-2004
> Yes. You are modifying the array element as they are being processed
> since the foreach variable is aliased to the array element and not
> a copy of the array element.


Thanks, since it's an aliase that explain everything.

DAE


 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      06-24-2004
"Daedalus" <(E-Mail Removed)> writes:

> "Anno Siegel" <(E-Mail Removed)-berlin.de> a écrit dans le message de
> news: cbeg3h$gii$(E-Mail Removed)-Berlin.DE...
> > Thomas Kratz <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > > Anno Siegel wrote:
> > >
> > > >
> > > > Your code (in all variants) has another problem. You are not supposed
> > > > to change an array while running a for-loop over it. (See "foreach"

> in
> > > > perlsyn, I suppose.) That it appears to work in this instance doesn't
> > > > mean it will with other versions of Perl.
> > >
> > > AFAIK you are not supposed to change the array, but changing the aliased
> > > elements should be ok.
> > >
> > > so:
> > >
> > > push(@array, $_) for @array # not recommended
> > >
> > > s/A/B/g for @array # ok
> > >
> > > Right?

> >
> > Right.

>
> Well the problem is that s///g don't do what I want, since it change every
> thing at the same time.


If you only want to change the first occurance in each string then
remove the /g.

If you want to append the changed version of the array to the original
array then why not:

s/A/B/g for my @array_copy = @array;
push @array, @array_copy;

> Anyway (for now) it couldn't turn into an infinite loop, since the content
> of the loop...


I asume you are talking about the effect of pushing into @array at the
same time with for().

How do you know that?

Bare in mind that the behaviour of for() when iterating over an array
that grows or shrinks is _undefined_. Undefined means anything could
happen, and also the thing that happens now may not be the thing that
happens in the next version of Perl.

If tomorrow the behaviour of pushing onto the array was to cause the
loop to reset to the start of the array then it could very well create
an infinite loop.

> I know it's not the perfect solution (and I'll try to find a better way
> while i'm on my learning process), so if someone have any idea... I'd be
> glad to correct this misuse.


See several better solutions already given in this thread.

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

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
stupid question...waiting for a stupid answer Brandon McCombs Java 4 08-28-2006 06:57 PM
Wrong answer equals to a blank answer or not? Zadkin Microsoft Certification 8 06-27-2006 01:51 PM
Stupid question. Please, only stupid responders. If you're not sureif you're stupid, you probably aren't. =?ISO-8859-1?Q?R=F4g=EAr?= Computer Support 6 07-18-2005 05:11 AM
stupid stupid stupid kpg MCSE 17 11-26-2004 02:59 PM



Advertisments