Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

cut columns with an array slice

by coldy (Scribe)
on Mar 15, 2011 at 04:36 UTC ( [id://893234]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks, I have an array of numbers that correspond to columns of an input file (space delimited) I need removed and need some advice: I have tried
#!/usr/bin/perl -w use strict; open(my $columns,"<",$ARGV[0]) or die("could not open $ARGV[0]!"); open(my $file,"<",$ARGV[1]) or die("could not open the $ARGV[1]!"); my @columns = <$columns>; chomp(@columns); while(<$file>) { my @arr=split(/\s+/,$_); print @arr[-@columns], "\n"; }

It is only printing one of the columns in the input file...

I think the problem is getting the '-' to preppend to each number in the array. How do I do this correctly? Thanks...

Replies are listed 'Best First'.
Re: cut columns with an array slice
by TGI (Parson) on Mar 15, 2011 at 05:33 UTC

    This is where showing sample data is really important if you want people to be able to help you. I am going to make some guesses about your data files and attempt to answer your question.

    First, I think your columns file looks like this:

    1 3 4 6

    If that's the case, then you are forgetting to split the columns data.

    In any case, you are doing something strange when you access the data array in your while loop.

    !/usr/bin/perl use strict; use warnings; my $col_file = shift; my $data_file = shift; open my $columns, '<', $col_file or die "Could not open $col_file - $!\n"; open my $file, '<', $col_file or die "Could not open $data_file - $!\n"); my @columns = split /\s+/, <$columns>; chomp(@columns); # use a hash for quick lookup of columns to skip # here I use a hash slice to assign undef values to the keys stored in + @columns my %skip; @skip{@columns} = (); while( my $line = <$file>) { chomp $line; my @raw_data = split /\s+/, $line; # Map and grep are a bit tough for newbies but they are important, + powerful tools that should be mastered. # Read from right to left: # Take the list of indexes in @raw_data # (grep) keep only those that do not exist as keys to %skip # (map) and look up the the item at that index in @raw_data # and finally print the resulting list. print join ' ', map $raw_data[$_], grep !exists $skip{$_}, 0..$#raw_data; print "\n"; }

    Accessing a negative array index indexes from the end of the array.

    Negating an array, causes the array to be evaluated in scalar context, yielding the number of members in the array. This value is then negated. So if @columns has 6 members, then -@columns is -6.

    Finally, a few points.

    • You can use a slice instead of map: print "@raw_data[ grep !exists $skip{$_}, 0..$#raw_data ]"; if you are strongly wedded to using an array slice.
    • If you know the width of your data file you can build your keep list outside the loop. my @keep = grep !exists $skip{$_}, 0..$width; ... print "@raw_data[@keep]\n";

      Update I made some updates with a few little bug fixes, and some extra points on slices and moving the keep list calculation out of the while loop. If things are suddenly different on you, that's why.


      TGI says moo

Re: cut columns with an array slice
by NetWallah (Canon) on Mar 15, 2011 at 05:21 UTC
    Another interpretation (untested) of what you might have intended:
    my %dont_want = map {$_=>undef} @columns; while (<$file>){ my @arr = split; print @arr[map {!exists $dont_want{$_}}0..$#arr],"\n"; }

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

Re: cut columns with an array slice
by Eliya (Vicar) on Mar 15, 2011 at 05:04 UTC
    @arr[map -$_, @columns]

    (if I'm understanding you correctly)

Re: cut columns with an array slice
by johngg (Canon) on Mar 15, 2011 at 10:42 UTC

    Use splice in a loop working with your columns to remove sorted in descending numerical order. In other words, by working in from the right of the array you don't mess up the indexing for subsequent operations. Note that I assume we are counting from column zero.

    knoppix@Microknoppix:/etc$ perl -E ' > open my $colsFH, q{<}, \ <<EOD or die qq{open: << HEREDOC: $!\n}; > 3 > 7 > 4 > EOD > > chomp( my @columns = <$colsFH> ); > close $colsFH or die qq{close: << HEREDOC: $!\n}; > > open my $dataFH, q{<}, \ <<EOD or die qq{open: << HEREDOC: $!\n}; > l1c0 l1c1 l1c2 l1c3 l1c4 l1c5 l1c6 l1c7 l1c8 l1c9 > l2c0 l2c1 l2c2 l2c3 l2c4 l2c5 l2c6 l2c7 l2c8 l2c9 > l3c0 l3c1 l3c2 l3c3 l3c4 l3c5 l3c6 l3c7 l3c8 l3c9 > EOD > > @columns = sort { $b <=> $a } @columns; > > while ( <$dataFH> ) > { > my @dataColumns = split; > splice @dataColumns, $_, 1 for @columns; > say join q{ }, @dataColumns; > } > > close $dataFH or die qq{close: << HEREDOC: $!\n};' l1c0 l1c1 l1c2 l1c5 l1c6 l1c8 l1c9 l2c0 l2c1 l2c2 l2c5 l2c6 l2c8 l2c9 l3c0 l3c1 l3c2 l3c5 l3c6 l3c8 l3c9 knoppix@Microknoppix:/etc$

    I hope this is helpful.

    Cheers,

    JohnGG

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://893234]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (6)
As of 2024-03-28 15:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found