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

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

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;

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

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

oops I mean I ALSO TRIED  s/^(CAT)/\$1 \$c+/e, @a; # single +

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

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>   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  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

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

]

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

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

-

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.

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

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)

[...]

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

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

>>   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> 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

uri

--
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

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

You are slow on the uptake :-)

I've been ignoring this poster for years.

--
email: perl -le "print scalar reverse qq/moc.liamg0cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.

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

>> but i don't think

TM> You are slow on the uptake :-)

and you just learned this now? :)

TM> I've been ignoring this poster for years.

TM>

yep, same old dog and no new tricks.

uri

--
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

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

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

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

Mr P wrote:

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

--
Ruud

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

Dr.Ruud wrote:

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

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

--
Ruud

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

Thank-You sir but I was looking for a "mapish" one-liner. I like your
style though!