awohld has asked for the wisdom of the Perl Monks concerning the following question:

I'm having trouble with this. If any of the first list elements in the AoA is set to a non numeric number, I want to change it to what my "$test" variable is set to.

In the example below, the "null" list element should be changed to "xray". How can I get this to work?
#!/usr/bin/perl -w use Data::Dumper; my @aoa; push @aoa, [ "null", "44", "4" ]; push @aoa, [ "6", "24", "6" ]; my $array = \@aoa; # show my data structure print Dumper $array; my $test = "xray"; # change first list element to variable "$test" if it isn't a number. @array = map { $_->[0] =~ s/[0-9]*/$test/ } @$array ; print Dumper \@array;

Replies are listed 'Best First'.
Re: AoA Selective Element Substitution
by johngg (Canon) on Jul 20, 2007 at 22:25 UTC
    Your problem is the regex you are using. Firstly, you need to negate the character class as [0-9] is going to match numbers, not the other was round. What you need is [^0-9]. Secondly, you should change the iterator from * (zero or more) to + (one or more). This is because zero or more digits will match at the beginning of the "null" element so you will get a replacement there resulting in "xraynull" and you will also change the "6" in the next array to "xray". Correcting the character class but leaving the iterator ([^0-9]*) will start to do the right thing with "null" but will make a mull of the first element of the next array resulting in "xray6".

    Incorporating both changes with [^0-9]+ does the right thing. Refactoring your code to incorporate strictures and create the data structure in one go

    use strict; use warnings; use Data::Dumper; my $raStruct = [ [ qw{null 44 4} ], [ qw{6 24 6} ], ]; print Data::Dumper->Dump([$raStruct], [q{raStruct}]); my $test = q{xray}; map { $_->[0] =~ s/[^0-9]+/$test/ } @$raStruct; print Data::Dumper->Dump([$raStruct], [q{raStruct}]);

    gives the following output

    $raStruct = [ [ 'null', '44', '4' ], [ '6', '24', '6' ] ]; $raStruct = [ [ 'xray', '44', '4' ], [ '6', '24', '6' ] ];

    I hope this is of use.

    Cheers,

    JohnGG

Re: AoA Selective Element Substitution
by FunkyMonk (Bishop) on Jul 20, 2007 at 21:35 UTC
    Using regexps in a map gets messy, so generally you don't want to do that.

    The following code changes the contents of $array (replacing your map line):

    for ( @$array ) { $_->[0] = $test if $_->[0] =~ m/\D/; }

    As a one liner, if that's important to you:

    $_->[0] =~ m/\D/ and $_->[0] = $test for @$array;
Re: AoA Selective Element Substitution
by shigetsu (Hermit) on Jul 20, 2007 at 22:48 UTC

    Albeit I concur mostly with FunkyMonk, just for the sake of completeness and something to play with (not everything here presented is a solution, and not even suitable sometimes (some of it is intentionally flawed - one should examine the output before using it); it tries to illustrate to a certain extent what is possible by using map):

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); { list_dump(sub { map { $_->[0] < 5 } @{set()} } ); list_dump(sub { map { $_->[2] < 5 ? $_ : () } @{set()} } ); list_dump(sub { map { [ map { $_ + 1 } @$_ ] } @{set()} } ); list_dump(sub { map { local $_ = $_; $_->[0] = 7; $_ } @{set()} } ); list_dump(sub { map { my @copy = @$_; [ map { $_ *= 2 } @copy ] +} @{set()} } ); sub list_dump (&) { my @list = $_[0]->(); print Dumper \@list; } sub set { return [ [1,2,3],[4,5,6] ]; } }