Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Creating a Slice through a 2 dimensional array

by felonius (Scribe)
on Sep 29, 2005 at 09:24 UTC ( #496023=perlquestion: print w/replies, xml ) Need Help??
felonius has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I've been reading 'The Book' and checking through past questions but think I must be misunderstanding something.

I've created a 2 dimensional array from a tab delimited file that has approx' 12 columns and around 12K lines. That bit works and by using Data::Dumper I can see all the data and know it's fine. I now want to take a slice through one column and all rows to sort on. Adapting the example from p272 of the camel book(3rd edition)  @part = @{ $AoA[4] } [7..12 ] I'm getting one line and all of it at that !. I know the problem is in specifying the range but can't quite see it. Could any of you open a new window onto this for me ?

Many thanks

Code as it stands so far is :

use strict; use Data::Dumper; my $filename = "Library.txt"; my @sortarr; my @sortslice; open (INPUT, $filename); my @array = <INPUT>; foreach my $array (@array) { push @sortarr, [ split(/\t/, $array) ]; } @sortslice = @{$sortarr[0..10]} [3]; print "@sortslice\n";

Replies are listed 'Best First'.
Re: Creating a Slice through a 2 dimensional array
by Zaxo (Archbishop) on Sep 29, 2005 at 09:52 UTC

    You don't need a slice if you're sorting the array reference members of @sortarr by a particular set of elements. Assuming numeric values, hence <=> comparisons,

    @sortarr = sort { $a->[3] <=> $b->[3] } @sortarr;
    If you want to sort on several columns, test in your desired order with logical-or between,
    @sortarr = sort { $a->[6] <=> $b->[6] || $a->[7] <=> $b->[7] || $a->[8] <=> $b->[8] || $a->[9] <=> $b->[9] || $a->[10] <=> $b->[10] || $a->[11] <=> $b->[11]; } @sortarr;
    Most of that is rarely executed because of the short circuit property of logical or. Looking up values by index is cheaper than copying out a 2-d slice sorting it and correlating the result to the original.

    If you do ever need slicing and other ops on deep arrays, see the great PDL module.

    After Compline,

Re: Creating a Slice through a 2 dimensional array
by xdg (Monsignor) on Sep 29, 2005 at 09:57 UTC

    Several issues -- first, your slice isn't a slice. You need @sortarr[0..10]. Second, the content of each element is an array reference -- you need to slice out each part of that. p.272 is throwing you off because it's giving a slice of a row -- you're trying for a slice of a column (in a row-major AoA).

    You probably want to use map to extract the subslices. E.g.

    my @aoa = ( [1 .. 4], [5 .. 8], [9 .. 12], ); my @column_slice = map { [ $_->[2] ] } @aoa[1,2]; my @two_d_slice = map { [ @{$_}[1,2] ] } @aoa[1,2];

    For a column slice, for each element of the slice, @aoa[1,2] (i.e. the rows), this dereferences the array reference to get the column, and returns it as a new anonymous array reference. (This keeps it an AoA; if you want a flattened list, omit the square brackets just inside the map braces.). For two-dimensions, it's similar, but you slice inside the map, too.


    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Creating a Slice through a 2 dimensional array
by tomazos (Deacon) on Sep 29, 2005 at 09:45 UTC
    So, $sortarr[0..10] is just plain wrong. (Does it compile? Confused.) It should be @sortarr[0..10] because a slice is plural (@) not singular ($).

    I can see what you are trying to do. You want the third column of the first ten lines in an array.

    You need to invert the Array-of-Arrays.

    Rather than an array of the split lines, you need an array of each column.

    You can do this with map, rather than a push split as you parse the file.

    Once you have it inverted you would say @sortarr[3]->[0..10] to get what you want.

    Update: Oh! I see why $sortarr[0..10] is compiling. It evaluates the array 0..10 in a scalar context, which gives you its length. It then uses this length as the index to a single element of @sortarr. use warnings may have helped. -Andrew.

    Andrew Tomazos  |  |
Re: Creating a Slice through a 2 dimensional array
by Roy Johnson (Monsignor) on Sep 29, 2005 at 12:34 UTC
Re: Creating a Slice through a 2 dimensional array
by felonius (Scribe) on Sep 29, 2005 at 10:05 UTC
    Many thanks for the replies. I see where I was going wrong - now to go away and try the suggestions !!

    Thanks again.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://496023]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2017-01-20 04:00 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (173 votes). Check out past polls.