Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Array elements in groups of 20

by jgiller (Novice)
on May 03, 2006 at 23:03 UTC ( [id://547295]=perlquestion: print w/replies, xml ) Need Help??

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

I have an array that consists of 32 elements. What I want to do is grab the first block of 20 elements from the array and perform some task on them. Then I want to grab the second block of whatever number of elements is left (lets say there is 12 left) and perform a task on them. I am using....
my @unique_vault_list; @tapes_for_box1 = $unique_vault_list[0..19]; @tapes_for_box2 = $unique_vault_list[20..$#unique_vault_list];
Neither subsequent array is giving me a list of at the most 20 elements as I would expect. Where am I going wrong? Thanks!

Replies are listed 'Best First'.
Re: Array elements in groups of 20
by cdarke (Prior) on May 03, 2006 at 23:10 UTC
    Use a slice, for example:
    @array[0..19]
    You were almost there. The sigil $ on an array indicates that a scalar index is inside the [], an @ indicates a list of indexes is inside the [] (same applies to hashes and {}). So you needed the @.
Re: Array elements in groups of 20
by ikegami (Patriarch) on May 03, 2006 at 23:58 UTC

    Other than the already suggested

    @tapes_for_box1 = @unique_vault_list[0..19]; @tapes_for_box2 = @unique_vault_list[20..$#unique_vault_list];

    you could use

    @tapes_for_box1 = splice(@unique_vault_list, 0, 20); @tapes_for_box2 = @unique_vault_list;

    which can be expanded into

    my @tapes_by_box; push(@tapes_by_box, [ splice(@unique_vault_list, 0, 20) ]) while @unique_vault_list;

    The difference is that splice removes the items from @unique_vault_list. (And it does so efficiently when removing from the start or end, as is the case here.)

Re: Array elements in groups of 20
by GrandFather (Saint) on May 03, 2006 at 23:14 UTC

    I recommend you read Flipin good, or a total flop? :). The short version is that you are geting the scalar range operator (scalar context) rather than the list you expected for a slice. The immediate fix is:

    use strict; use warnings; my @unique_vault_list = (1..32); my @tapes_for_box1 = @unique_vault_list[0..19]; my @tapes_for_box2 = @unique_vault_list[20..$#unique_vault_list]; print "Box 1: @tapes_for_box1\n"; print "Box 2: @tapes_for_box2\n";

    Prints:

    Box 1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Box 2: 21 22 23 24 25 26 27 28 29 30 31 32

    An alternative if you don't mind clobbering your original list (or making a copy of it) is:

    use strict; use warnings; my @unique_vault_list = (1..32); my @tapes_for_box1 = splice @unique_vault_list, 0, 20; my @tapes_for_box2 = splice @unique_vault_list, 0, 20; print "Box 1: @tapes_for_box1\n"; print "Box 2: @tapes_for_box2\n";

    Prints:

    Box 1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Box 2: 21 22 23 24 25 26 27 28 29 30 31 32

    DWIM is Perl's answer to Gödel
Re: Array elements in groups of 20
by Cristoforo (Curate) on May 03, 2006 at 23:17 UTC
    @tapes_for_box1 = @unique_vault_list[0..19]; @tapes_for_box2 = @unique_vault_list[20..$#unique_vault_list];
    you are using slices, so you need to use @ instead of the singular $ prefix to your array 'unique_vault_list'

    Chris

Re: Array elements in groups of 20
by Hue-Bond (Priest) on May 04, 2006 at 08:12 UTC
    What I want to do is grab the first block of 20 elements from the array and perform some task on them. Then I want to grab the second block of whatever number of elements is left (lets say there is 12 left) and perform a task on them.

    And what will happen when your requirements change and you need, say, 13 elements instead of 20? You'll have to change your code so that 0..19 becomes 0..12, 20..32 becomes 13..25 and you'll have to add another iteration for the elements 26..$#unique_vault_list. That is partly addressed by the splice solution but I think List::MoreUtils' natatime function would be better suited for this:

    use List::MoreUtils qw/natatime/; my @unique_vault_list = 0..31; my $iter = natatime 20, @unique_vault_list; while (my @cur = $iter->()) { ## now you have each group of 20 elements in @cur print "@cur\n"; } __END__ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

    This way, you don't have to work with @tapes_for_box1, @tapes_for_box2 and maybe @tapes_for_box3...

    --
    David Serrano

Re: Array elements in groups of 20
by santonegro (Scribe) on May 04, 2006 at 16:44 UTC

Log In?
Username:
Password:

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

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

    No recent polls found