tags:

views:

476

answers:

6

When I am running the following statement:

@filtered = map {s/ //g} @outdata;

it is returning an empty list instead of the filtered list that I expected. What I am trying to do is remove every occurance of   from an array of string (which is an XML file).

Obviously, I am not understanding something. Can anyone tell me the correct way to do this, and why this isn't working for me

+8  A: 

Try this:

@filtered = map {s/ //g; $_} @outdata;

The problem is the s operator in perl modifies $_ but actually returns the number of changes it made. So, the extra $_ at the end causes perl to return the modified string for each element of @outdata.

Greg Hewgill
This code trashes the values in @outdata.
Kevin Panko
I'm not feeling mean enough to downvote, but this is a Bad Idea. http://stackoverflow.com/questions/12103/why-doesnt-my-perl-map-return-anything/21792#21792 is a much better answer.
Rob Van Dam
+2  A: 

As a counterpoint to Greg's answer, you could misuse grep:

@filtered = grep {s/ //g; 1} @outdata;

Don't do this.

Cebjyre
+10  A: 

Note that map is going to modify your source array as well. So you could either do:

map {s/ //g} @outdata;

and skip the @filtered variable altogether, or if you need to retain the originals,

@filtered = @outdata;
map {s/ //g} @filtered;

Although, in that case, it might be more readable to use foreach:

s/ //g foreach @filtered;
Tithonium
+4  A: 

To follow up on Tithonium's point, this will also do the trick:

@filtered = map {local $_=$_; s/ //g; $_} @outdata;

The "local" ensures you're working on a copy, not the original.

Michael Cramer
+5  A: 

Greg's answer has the problem that it will modify the original array as the $_ are passed aliased. You need:

@filtered = map { (my $new = $_) =~ s/ //g; $new} @outdata;
Shlomi Fish
+3  A: 
use Algorithm::Loops "Filter";
@filtered = Filter { s/ //g } @outdata;
ysth