=pod =head1 buckets buckets (size=> N, els=> \@ARRAY ,opt[ ref_to=>\&CODE ] ); Given a size and an array reference, splits the array into an AoA with each element being a reference to an array whose elements are les +s than C<size> in total. If an element is larger than C<size> it is placed in +to a single "bucket". If the elements of the original array are more complex then numeric sc +alars, you can pass a code ref that returns access to the criteria element. Example: my @array = (10 ,9 , 15, 40, 67, 2, 35); my @res = buckets(size=>30, els=>\@array); \@res = [ [ 50 ], [ 67 ], [ 40 ], [ 15, 10 ], [ 9, 2 ] ]; Or with references.. my @array = ( ['foo',10 ], ['bar', 4 ], ['base', 18 ], ['foobar',5 ], + ) ; my @res = buckets(size=>30, els=>\@array, ref_to=>sub { $_->[1] } ); It does not attempt to find the optimal set of elements. It simply sor +ts the values in reverse numeric order. =cut sub buckets { my %args = @_; die "missing size argument: " unless defined $args{size}; die "argument element is not an ARRAY reference: $args{els}" unless UNIVERSAL::isa($args{els},'ARRAY'); die "argument ref_to is not a CODE reference: $args{ref_to}" if defined $args{ref_to} and !UNIVERSAL::isa($args{r +ef_to},'CODE'); return () unless @{$args{els}}; my @orig = @{$args{els}}; my @els = defined $args{ref_to} ? sort { $b->[0] <=> $a->[0] } map { [ &{$args{ref_to}}, $_ ] } + @orig : sort {$b <=> $a} @orig; my ($size,@res) = (0); local $_; { $_ = shift @els; $_ = $_->[1] if $args{ref_to}; my $el = $args{ref_to} ? &{$args{ref_to}} : $_ ; $size = push(@res,[]) && 0 if $size + $el > $args{size} or $el +> $args{size} ; $size+=$el; push @{$res[-1]}, $_; redo if @els; } @res; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
•Re: Split array into smaller arrays by total of element values
by merlyn (Sage) on Jun 11, 2003 at 02:35 UTC | |
by shotgunefx (Parson) on Jun 11, 2003 at 09:33 UTC |