Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > How can I use MAP to increment values in an array?

Reply
Thread Tools

How can I use MAP to increment values in an array?

 
 
Mr P
Guest
Posts: n/a
 
      05-10-2010
I have an array in which I want to add a counter - for example, change
CAT to CAT #:

....so
CAT
DOG
CAT
MOUSE
EEL
CAT

becomes
CAT 1
DOG
CAT 2
MOUSE
EEL
CAT 3

Obviously I can write a little loop like

my $c = 0;
for ( @a )
{
next unless /^CAT/;
$c++; # wow that's weird
$_ .= " $c";
}

But what I'd prefer is something like

my $c = 1;
map s/^(CAT)/$1 $c++/e, @a;

I read and read on this, and I also tried:
map s/^(CAT)/$1 $c++/e, @a;

since it appeared that within the RHS of the s///, a single + was an
increment operator.

Am I in the ballpark here guys? Everything I've tried results in
interpreter errors.

Thanks,
MP
 
Reply With Quote
 
 
 
 
Mr P
Guest
Posts: n/a
 
      05-10-2010
On May 10, 3:44*pm, Mr P <(E-Mail Removed)> wrote:
> I have an array in which I want to add a counter - for example, change
> CAT to CAT #:
>
> ...so
> CAT
> DOG
> CAT
> MOUSE
> EEL
> CAT
>
> becomes
> CAT 1
> DOG
> CAT 2
> MOUSE
> EEL
> CAT 3
>
> Obviously I can write a little loop like
>
> my $c = 0;
> for ( @a )
> {
> * next unless /^CAT/;
> * $c++; # wow that's weird
> * $_ .= " $c";
> *}
>
> But what I'd prefer is something like
>
> * my $c = 1;
> * map s/^(CAT)/$1 $c++/e, @a;
>
> I read and read on this, and I also tried:
> * map s/^(CAT)/$1 $c++/e, @a;
>
> since it appeared that within the RHS of the s///, a single + was an
> increment operator.
>
> Am I in the ballpark here guys? Everything I've tried results in
> interpreter errors.
>
> Thanks,
> MP


oops I mean I ALSO TRIED s/^(CAT)/$1 $c+/e, @a; # single +
 
Reply With Quote
 
 
 
 
Uri Guttman
Guest
Posts: n/a
 
      05-10-2010
>>>>> "P" == P <(E-Mail Removed)> writes:

P> my $c = 0;
P> for ( @a )
P> {
P> next unless /^CAT/;
P> $c++; # wow that's weird

wierd in what way?

P> $_ .= " $c";
P> }

P> But what I'd prefer is something like

P> my $c = 1;
P> map s/^(CAT)/$1 $c++/e, @a;

that won't work. the replacement is an expression with /e. you are
thinking it is a string AND an expression. so make an expression
(multiple statements are allowed) with the last one being the
replacement value. something like this: (untested)

s/^(CAT)/$c++ ; "$1 $c:/e foreach @a;

and don't use map without returning a list. foreach modifier is better
for that.

P> I read and read on this, and I also tried:
P> map s/^(CAT)/$1 $c++/e, @a;

P> since it appeared that within the RHS of the s///, a single + was an
P> increment operator.

huh??

P> Am I in the ballpark here guys? Everything I've tried results in
P> interpreter errors.

well, everything you tried is a syntax error. as i said, the code in the
replacement part must be a valid expression under /e.

this by itself is not valid perl:

$1 $c++

uri

--
Uri Guttman ------ http://www.velocityreviews.com/forums/(E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Dr.Ruud
Guest
Posts: n/a
 
      05-10-2010
Mr P wrote:
> I have an array in which I want to add a counter - for example, change
> CAT to CAT #:
>
> ....so
> CAT
> DOG
> CAT
> MOUSE
> EEL
> CAT
>
> becomes
> CAT 1
> DOG
> CAT 2
> MOUSE
> EEL
> CAT 3


perl -MData:umper -wle'
my (@r, %c);
push @r, [$_, ++$c{$_}]
for qw/ CAT DOG CAT MOUSE EEL CAT /;
print Dumper(\@r);
'

--
Ruud
 
Reply With Quote
 
Dr.Ruud
Guest
Posts: n/a
 
      05-10-2010
Dr.Ruud wrote:
> Mr P wrote:


>> I have an array in which I want to add a counter - for example, change
>> CAT to CAT #:
>>
>> ....so
>> CAT
>> DOG
>> CAT
>> MOUSE
>> EEL
>> CAT
>>
>> becomes
>> CAT 1
>> DOG
>> CAT 2
>> MOUSE
>> EEL
>> CAT 3

>
> perl -MData:umper -wle'
> my (@r, %c);
> push @r, [$_, ++$c{$_}]
> for qw/ CAT DOG CAT MOUSE EEL CAT /;
> print Dumper(\@r);
> '


And use %c to decide whether you want to print the "1".

perl -MData:umper -wle'
my (@r, %c, $k);
push @r, [$_, ++$c{$_}] for qw/ CAT DOG CAT MOUSE EEL CAT /;
print $k=$_->[0], $c{$k}>1 ? " $_->[1]" : "" for @r;
'
CAT 1
DOG
CAT 2
MOUSE
EEL
CAT 3

--
Ruud
 
Reply With Quote
 
Mr P
Guest
Posts: n/a
 
      05-11-2010
]
> * P> * $c++; # wow that's weird
>
> wierd in what way?

Weird in that the variable name accidentally stumbled on another
language? Just a little bad humor Uri no worries..

>
> * P> * $_ .= " $c";
> * P> *}
>
> * P> But what I'd prefer is something like
>
> * P> * my $c = 1;
> * P> * map s/^(CAT)/$1 $c++/e, @a;
>
> that won't work. the replacement is an expression with /e. you are
> thinking it is a string AND an expression. so make an expression
> (multiple statements are allowed) with the last one being the
> replacement value. something like this: (untested)
>
> s/^(CAT)/$c++ ; "$1 $c:/e foreach @a;
>
> and don't use map without returning a list. foreach modifier is better
> for that.

respectfully- this is just another way to specify a for loop-
precisely what I was trying to avoid..


>
> * P> I read and read on this, and I also tried:
> * P> * map s/^(CAT)/$1 $c++/e, @a;
>
> * P> since it appeared that within the RHS of the s///, a single + was an
> * P> increment operator.
>
> huh??

Maybe I mis-read
>
> * P> Am I in the ballpark here guys? Everything I've tried results in
> * P> interpreter errors.
>
> well, everything you tried is a syntax error. as i said, the code in the
> replacement part must be a valid expression under /e.
>
> this by itself is not valid perl:
>
> $1 $c++
>
> uri

-
> --------- *Gourmet Hot Cocoa Mix *---- *http://bestfriendscocoa.com---------


Thanks Uri and everyone, but to summarize , what I'm attempting to do,
apparently, isn't supported..

It seems odd to me that it's not, I want to MAP an incremented value
over an array- sounds like a perfectly logical thing to want to do?

I realize of course from my, and everyone else's contributions, there
are myriad ways to accomplish this with for or foreach. But that's
precisely what I DID NOT want to do. THat's the beauty and elegance of
map- it operates in 2D.
 
Reply With Quote
 
Mr P
Guest
Posts: n/a
 
      05-11-2010

>
> perl -MData:umper -wle'
> * *my (@r, %c);
> * *push @r, [$_, ++$c{$_}]
> * * *for qw/ CAT DOG CAT MOUSE EEL CAT /;
> * *print Dumper(\@r);
> '
>
> --
> Ruud


Thank-You sir but I was looking for a "mapish" one-liner. I like your
style though!
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      05-11-2010
On 2010-05-11 19:18, Mr P <(E-Mail Removed)> wrote:
>>
>> * P> * $_ .= " $c";
>> * P> *}
>>
>> * P> But what I'd prefer is something like
>>
>> * P> * my $c = 1;
>> * P> * map s/^(CAT)/$1 $c++/e, @a;
>>
>> that won't work. the replacement is an expression with /e. you are
>> thinking it is a string AND an expression. so make an expression
>> (multiple statements are allowed) with the last one being the
>> replacement value. something like this: (untested)
>>
>> s/^(CAT)/$c++ ; "$1 $c:/e foreach @a;
>>
>> and don't use map without returning a list. foreach modifier is better
>> for that.

> respectfully- this is just another way to specify a for loop-
> precisely what I was trying to avoid..


In some sense map is also just another way to specify a for loop.

The difference is mainly that map returns a result, but for doesn't. So
the rule in perl is: If you are interested in the result, use map.
Otherwise use for.

You don't use the result of the map, so you should use for.
(it does the same thing, but it's more readable)


>> * P> I read and read on this, and I also tried:
>> * P> * map s/^(CAT)/$1 $c++/e, @a;

[...]
>> well, everything you tried is a syntax error. as i said, the code in the
>> replacement part must be a valid expression under /e.
>>
>> this by itself is not valid perl:
>>
>> $1 $c++
>>

>
> Thanks Uri and everyone, but to summarize , what I'm attempting to do,
> apparently, isn't supported..


It is. Uri already gave you one solution. Plus several hints in the
right direction.

I'll give you another hint:

Uri wrote that
$1 $c++
by itself is not valid perl.

You cannot (for example) write
$x = $1 $c++;

How would you write this line, so that it becomes valid Perl and does
what you want? If you know this you also know how to rewrite your
substitution so that it works.

hp
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      05-11-2010
>>>>> "P" == P <(E-Mail Removed)> writes:

>> * P> * my $c = 1;
>> * P> * map s/^(CAT)/$1 $c++/e, @a;
>>
>> that won't work. the replacement is an expression with /e. you are
>> thinking it is a string AND an expression. so make an expression
>> (multiple statements are allowed) with the last one being the
>> replacement value. something like this: (untested)
>>
>> s/^(CAT)/$c++ ; "$1 $c:/e foreach @a;
>>
>> and don't use map without returning a list. foreach modifier is better
>> for that.


P> respectfully- this is just another way to specify a for loop-
P> precisely what I was trying to avoid..

huh?? map IS a loop too! you are just using map for the loop and not for
the primary purpose which is to return a list. since you don't return a
list, don't mislead the code reader with map. use foreach modifier which
says i am doing something in a loop and not building up a list.
>>
>> * P> I read and read on this, and I also tried:
>> * P> * map s/^(CAT)/$1 $c++/e, @a;
>>
>> * P> since it appeared that within the RHS of the s///, a single + was an
>> * P> increment operator.
>>
>> huh??

P> Maybe I mis-read
>>
>> * P> Am I in the ballpark here guys? Everything I've tried results in
>> * P> interpreter errors.
>>
>> well, everything you tried is a syntax error. as i said, the code in the
>> replacement part must be a valid expression under /e.
>>
>> this by itself is not valid perl:
>>
>> $1 $c++
>>
>> uri

P> -
>> --------- *Gourmet Hot Cocoa Mix *---- *http://bestfriendscocoa.com---------


P> Thanks Uri and everyone, but to summarize , what I'm attempting to do,
P> apparently, isn't supported..

no, your brain isn't supporting it. perl can do what you want as long as
you code it correctly. you have SYNTAX errors in your code. as well as a
misunderstanding of the semantics of /e.

P> It seems odd to me that it's not, I want to MAP an incremented value
P> over an array- sounds like a perfectly logical thing to want to do?

stop capitalizing MAP. it is map and you really want foreach modifier as
i keep saying. otherwise you are misleading the code reader. this is not
an obsfucation contest, use the correct feature.

P> I realize of course from my, and everyone else's contributions,
P> there are myriad ways to accomplish this with for or foreach. But
P> that's precisely what I DID NOT want to do. THat's the beauty and
P> elegance of map- it operates in 2D.

no it doesn't. you don't get map vs foreach modifier vs a full
loop. they ALL LOOP. they are different in syntax and semantics but they
are all loops. you need a loop. even a /g on your s/// will be a
LOOP. you can't avoid LOOPS if you want to do something over and over.

and you can even avoid map likely with a /g modifier. but i don't think
i will help you until you learn about perl LOOPS, implied or explicit.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      05-11-2010
Mr P wrote:
)> s/^(CAT)/$c++ ; "$1 $c:/e foreach @a;
)>
)> and don't use map without returning a list. foreach modifier is better
)> for that.
) respectfully- this is just another way to specify a for loop-
) precisely what I was trying to avoid..

map is also just another way to specify a for loop.

) Thanks Uri and everyone, but to summarize , what I'm attempting to do,
) apparently, isn't supported..

Of course it is. If you want to keep the original array intact,
and you want a *new* array with the counters added, *then* map is
useful:

my $c = 0;
my @result = map { $_.(/^CAT$/ && ' '.++$c) } @source;

But that's still a loop over each separate element of the array.

) It seems odd to me that it's not, I want to MAP an incremented value
) over an array- sounds like a perfectly logical thing to want to do?
)
) I realize of course from my, and everyone else's contributions, there
) are myriad ways to accomplish this with for or foreach. But that's
) precisely what I DID NOT want to do. THat's the beauty and elegance of
) map- it operates in 2D.

No it doesn't. It's just a for loop that returns an array of results.

This is map, basically:

sub map (&@) {
my $func = shift;
my @result;
push @result, &$func for @_;
return @result;
}

If you don't use the result of map, then it is *exactly* the same as for.
(In recent versions of perl, map even checks if it is called in a void
context, and if so it switches to a for-loop.)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
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
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Re: Post increment ++ has higher precedence than pre increment ++. Why? Alf P. Steinbach /Usenet C++ 0 05-22-2011 12:03 PM
why prefix increment is faster than postfix increment? jrefactors@hotmail.com C++ 99 06-11-2010 12:51 PM
post increment or pre increment? Peng Yu Perl Misc 7 11-23-2008 11:44 PM
why prefix increment is faster than postfix increment? jrefactors@hotmail.com C Programming 104 10-27-2005 11:44 PM



Advertisments