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

M

Mr P

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
 
M

Mr P

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

Uri Guttman

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
 
D

Dr.Ruud

Mr said:
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::Dumper -wle'
my (@r, %c);
push @r, [$_, ++$c{$_}]
for qw/ CAT DOG CAT MOUSE EEL CAT /;
print Dumper(\@r);
'
 
D

Dr.Ruud

Dr.Ruud said:
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::Dumper -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::Dumper -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
 
M

Mr P

]
  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.
 
M

Mr P

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

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

Peter J. Holzer

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
 
U

Uri Guttman

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

Willem

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top