Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Creating a Slice through a 2 dimensional array

by felonius (Scribe)
on Sep 29, 2005 at 09:24 UTC ( [id://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
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://496023]
Approved by Corion
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (2)
As of 2024-06-22 13:35 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.