Tutorial :Map with Split & Trim in Perl



Question:

How do I use map with the split function to trim the constituents: $a, $b, $c and $d; of $line?

my ($a, $b, $c, $d, $e) = split(/\t/, $line);    # Perl trim function to remove whitespace from the start and end of the string  sub trim($)  {      my $string = shift;      $string =~ s/^\s+//;      $string =~ s/\s+$//;      return $string;  }  


Solution:1

Don't use prototypes the ($) on your function unless you need them.

my ( $a, $b, $c, $d, $e ) =    map {s/^\s+|\s+$//g; $_}    ## Notice the `, $_` this is common    , split(/\t/, $line, 5)  ;  

Don't forget in the above s/// returns the replacement count -- not $_. So, we do that explicitly.

or more simply:

my @values = map {s/^\s+|\s+$//g; $_}, split(/\t/, $line, 5), $line  


Solution:2

map takes two inputs:

  • an expression or block: this would be the trim expression (you don't have to write your own -- it's on CPAN)
  • and a list to operate on: this should be split's output:
use String::Util 'trim';  my @values = map { trim($_) } split /\t/, $line;  


Solution:3

This should work:

my ($a, $b, $c, $d, $e) = map {trim ($_)} (split(/\t/, $line));  

By the way, it's a minor point, but you should not use $a and $b as variable names.


Solution:4

You can also use "foreach" here.

foreach my $i ($a, $b, $c, $d, $e) {    $i=trim($i);  }  


Solution:5

Just for variety:

my @trimmed = grep { s/^\s*|\s*$//g } split /\t/, $line;  

grep acts as a filter on lists. This is why the \s+s need to be changed to \s*s inside the regex. Forcing matches on 0 or more spaces prevents grep from filtering out items in the list that have no leading or trailing spaces.


Solution:6

When I trim a string, I don't often want to keep the original. It would be nice to have the abstraction of a sub but also not have to fuss with temporary values.

It turns out that we can do just this, as perlsub explains:

Any arguments passed in show up in the array @_. Therefore, if you called a function with two arguments, those would be stored in $_[0] and $_[1]. The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated (or an error occurs if it is not updatable).

In your case, trim becomes

sub trim {    for (@_) {      s/^ \s+  //x;      s/  \s+ $//x;    }    wantarray ? @_ : $_[0];  }  

Remember that map and for are cousins, so with the loop in trim, you no longer need map. For example

my $line = "1\t 2\t3 \t 4 \t  5  \n";      my ($a, $b, $c, $d, $e) = split(/\t/, $line);        print "BEFORE: [", join("] [" => $a, $b, $c, $d), "]\n";  trim $a, $b, $c, $d;  print "AFTER:  [", join("] [" => $a, $b, $c, $d), "]\n";  

Output:

BEFORE: [1] [ 2] [3 ] [ 4 ]  AFTER:  [1] [2] [3] [4]

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »