Why doesn't my Perl map return anything?

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 occurrence 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 might be, and why this isn't working for me as is?

Mengomentari pertanyaan (1)

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;
Komentar (1)
Larutan

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.

Komentar (3)

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;
Komentar (0)

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.

Komentar (0)

In perl 5.14 you could use the /r regex modifier to make non-destructive substitution.

@filtered = map {s/ //gr} @outdata;
Komentar (0)
use Algorithm::Loops "Filter";
@filtered = Filter { s/ //g } @outdata;
Komentar (0)

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

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

Don't do this.

Komentar (0)