Limbic~Region has asked for the wisdom of the Perl Monks concerning the following question:

All:
While tracking down an interesting bug in some of my code, I discovered that while chomp can take a list such as an array, it doesn't work quite right on an AoA. Consider the following:

#!/usr/bin/perl -w use strict; my @Fields; my @Array; open (FILE,"file") or die "Can't open file\n"; while (<FILE>) { next if (/^#/); @fields = split "\t" , $_; next unless (@Fields == 7); push @Array , [ @Fields[0,3,6] ]; } foreach my $foo (@fields) { print "$foo->[2]\n" if ($foo->[2] != 3); }

You are confused as to why the code won't work (scratching head) - oh, I see my mistake - there is a trailing newline at the end - let me just get rid of it.

push @Array , [ @Fields[0,3,6] ]; } chomp @Array; foreach my $foo (@fields) { print "$foo->[2]\n" if ($foo->[2] != 3); }

Now it still doesn't work - this time you are getting some error about not being able to use a stringified array as a reference with strict enforced.

you remove the chomp as is and you put it back in the code that builds the array

while (<FILE>) { next if (/^#/); @fields = split "\t" , $_; next unless (@Fields == 7); chomp $Fields[6]; push @Array , [ @Fields[0,3,6] ]; }

You are happy your code is now working, but you are sad that you have to do it THAT way.

so friendly monks - is there a way to chomp an AoA similar to:

chomp @Array;

Thanks in advance - L~R

Replies are listed 'Best First'.
Re: Chomp an AoA?
by Gilimanjaro (Hermit) on Jan 28, 2003 at 20:49 UTC
    First of all, why would you want to chomp anything that did not directly result from a <> read? perlfunc states that chomp chomps a trailing $/, which you are guaranteed only to see when reading using <> brackets... I always do the chomp as the first statement in the loop. When I'm in a daring mood I even put it in the while clause...

    Secondly, I think you might be mistaking an array for a list... Which I always did until I read Arrays are not lists by tilly. If that is the case, then chomp would probably work if you did:

    chomp @Array[0..$#Array];

    If that ain't it, I humbly apologize... :)

    Update: Read original post again; seems logical to me chomp won't work as you suggest; an AoA is really an AoRA (Array of references to arrays) and you can hardly expect chomp to merily go dereferencing elements of the array it's passed...

    I am now even more so convinced the chomp should just be moved up in the loop, where it belongs...

      You are exactly right. He should be chomp'ing in his while loop, right between next unless (@Fields == 7); and push @Array , [ @Fields[0,3,6] ];. A nice juicy chomp @Array;


      MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
      ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: Chomp an AoA?
by chromatic (Archbishop) on Jan 28, 2003 at 21:53 UTC

    chomp works on a list of strings. An array of array references listifies to a list of array references, which are stringified, which doesn't do what you want.

    Why not just chomp each line as you read it, before you split it?

Re: Chomp an AoA?
by integral (Hermit) on Jan 28, 2003 at 19:16 UTC
    A simple way of coding this inline would be to do a
    map { chomp @$_ } @_;

    But while this would solve your problem isn't not a generic recursive chomp.

Re: Chomp an AoA?
by dempa (Friar) on Jan 28, 2003 at 19:10 UTC

    Maybe not the answer you want, but I would use Juerds snippet for this.

    Semi-OT random ramblings: I took Juerds snippet and modified it into two new functions: base64_encode_struct and base64_decode_struct. Instead of chomp:ing the data I encoded/decoded it with MIME::Base64. Useful if you have a complex data structure that you want to use with XML::Simple but you want to Base64-encode the data (not the tags).

    -- 
    dempa

Re: Chomp an AoA?
by Aristotle (Chancellor) on Jan 31, 2003 at 03:18 UTC
    To chomp all elements you could
    chomp @$_ for @array; # or chomp map @$_, @array;
    However since you only want to chomp one of them
    chomp map $_->[2], @array;
    But why add another loop if you can do it inline?
    while (<FILE>) { next if /^#/ or tr/\t// != 6; chomp; push @array, [ split "\t" ]; }

    Makeshifts last the longest.