http://qs321.pair.com?node_id=448139

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

Dear Monks, Does anyone know a neat way to split an array up every 50 elements? The array is quite big.

Thanks!

Replies are listed 'Best First'.
Re: splitting arrays
by RazorbladeBidet (Friar) on Apr 15, 2005 at 13:02 UTC
    splice perhaps? Your question is just a tad vague, care to give us more info?
    --------------
    "But what of all those sweet words you spoke in private?"
    "Oh that's just what we call pillow talk, baby, that's all."
      Hi

      I am reading in a file of data, each line has 50 bits of tab-delimited data. I normally use split but for some reason, some items have lots of newline characters seperating the data and some don't. I am doing this within a while loop but it is considering every line as a separate record, not every item.

      while (<ARRAY_DATA>) { $line = $_; chomp ($line); @array = (); @array = split (/\s+/, $line); # other stuff here }
        So are you saying that inside that line of 50 items (I'm assuming you're using the term "bits" to mean "things" not 0 or 1) there are newline characters? If so, what is the line termination character - how do you know when you need to start on the next "line".
        --------------
        "But what of all those sweet words you spoke in private?"
        "Oh that's just what we call pillow talk, baby, that's all."
        If your goal is to read 50 items into an array on each pass of the loop:
        while (!eof DATA) { local $/="\t"; chomp(my @set = map {(eof) ? () : scalar(<DATA>)} 1..50); print "Set: ", join(',', @set), "\n"; }
        Use whatever filehandle is appropriate.
        Update: changed second eof to use "last file read" default form.

        Caution: Contents may have been coded under pressure.
Re: splitting arrays
by Zaxo (Archbishop) on Apr 15, 2005 at 13:03 UTC
Re: splitting arrays
by Taulmarill (Deacon) on Apr 15, 2005 at 13:22 UTC
    this will destroy your old array, but should give you the result you want
    use strict; use warnings; my @bigArry = 0 .. 99; my $max = 17; my @sliced; push @sliced, [ splice @bigArry, 0, $max ] while @bigArry; use Data::Dumper; print Dumper \@sliced;
Re: splitting arrays
by TedPride (Priest) on Apr 15, 2005 at 13:42 UTC
    That solution isn't terribly efficient, however, since the entire array (which is specified as being huge) has to be rewritten for every splice. You're splicing from the start, not the end, and might do better splicing in reverse and then reversing. Alternately, you could make a copy of the array contents instead of splicing:
    use strict; use warnings; my (@arr, @arr2, $i); $arr[$_] = $_ for 0..357; for ($i = 0; $i <= $#arr; $i += 50) { push @arr2, [@arr[$i..($i+49)]]; } $#{$arr2[$#arr2]} = $#arr % 50; print join(' ', @$_), "\n" for @arr2;
    Yes, this has a memory cost twice that of the original array, but you're going to need that even with the spliced solution, since I don't believe the extra space is returned to the script as the array is reduced in size?
Re: splitting arrays
by sh1tn (Priest) on Apr 15, 2005 at 14:20 UTC
    What's wrong with splice?
    my @A = 11..40; my $start = 0; my $stop = 5; print((splice@A, $start, $stop),$/) while @A; __END__ STDOUT: 1112131415 1617181920 2122232425 2627282930 3132333435 3637383940


Re: splitting arrays
by NateTut (Deacon) on Apr 15, 2005 at 18:54 UTC
    Instead of trying to read the file a line at a time when you do not have any line terminators try using read to get only 50 bytes at a time (not bits).