Re: list to LoL
by lhoward (Vicar) on Jun 02, 2000 at 21:28 UTC
|
Here's my solution.... There's some unclean code
in there to make it handle fencepost conditions that I could
probably optimize out, but haven't yet. Would also be faster
if I passed array references in and out of the reform_list subroutine.
use Data::Dumper;
my @a=(1..100);
my @a3=reform_list(3,@a);
print Dumper(@a3);
my @a4=reform_list(4,@a);
print Dumper(@a4);
sub reform_list{
my $size=shift;
my @list=@_;
my @nlist=();
my $max=int(scalar(@list)/$size);
for(my $c=0;$c<=$max;$c++){
my $a=$c*$size;
my $b=($c+1)*$size-1;
if($b>=scalar(@list)){
$b=scalar(@list)-1;
}
if($a<=$b){
push @nlist,[@list[$a..$b]];
}
}
return @nlist;
}
I've done some quick benchmarking and all 3 of the methods
posted so far are very equivalent when it comes to performance
(tests below are on a 1000 element array arranging it into
sub-arrays of 5 elements each)
| submitter | benchmark |
| adam | 6 wallclock secs ( 5.59 usr + 0.00 sys = 5.59 CPU) @ 894.45/s (n=5000) |
| lhoward | 6 wallclock secs ( 5.79 usr + 0.00 sys = 5.79 CPU) @ 863.56/s (n=5000) |
| swiftone | 6 wallclock secs ( 5.71 usr + 0.00 sys = 5.71 CPU) @ 875.66/s (n=5000) |
Testing with other parameters (different list sizes and
split sizes) shows different algorithms faster.
All algorithms continue to stay
very closely grouped performance wise
(though I am happy to report that my algorithm appears
to be slightly fastest for larger lists).
I've managed to clean up my code a little (though these changes
didn't make it any faster). It doesn't look quite as
ugly and still handles the fencepost conditions properly.
sub reform_list{
my $size=shift;
my @list=@_;
my @nlist=();
my $list_size=scalar(@list);
my $c;
my $stop=int($list_size/$size)*$size;
for($c=0;$c<$stop;$c+=$size){
push @nlist,[@list[$c..($c+$size-1)]];
}
if($c<$list_size){
push @nlist,[@list[$c..($list_size-1)]];
}
return @nlist;
}
| [reply] [d/l] [select] |
|
|
lhoward and zzamboni are the greatest!!!!
THANK YOU VERY MUCH!!!!
You are both lifesavers.
swiftone and adam, thank you very much as well.
| [reply] |
|
|
| [reply] |
Re: list to LoL
by swiftone (Curate) on Jun 02, 2000 at 21:20 UTC
|
sub lolize {
my ($size, $inarrayref)= @_;
my $count=0;
my @temparray=();
my @returnarray=();
foreach (@$inarrayref){
push @temparray, $_;
$count++;
if($count==$size){
print @temparray, "\n";
push @returnarray, [@temparray];
@temparray=();
$count=0;
}
}
return [@returnarray];
}
You'd call it with &lolize($count, $listref); | [reply] [d/l] |
RE: list to LoL
by Adam (Vicar) on Jun 02, 2000 at 21:21 UTC
|
I'm still working on some code, but I think you could do it with a loop and splice.Ok, here is my code: @A=(1,2,3,4,5,6,7,8,9); # some array
$n = 3; # some n
while( @B = splice @A, $i++, $n ) { @A= ( [@B], @A ) };
@A = reverse @A; # To put it back in the right order.
And yes, that blows away the old @A. | [reply] [d/l] |
|
|
sub lolize{
my($size, $arrayref)=@_;
my @returnarray=();
my $count=0;
while($count<=$@arrayref){
push @returnarray, [splice(@$arrayref,$count, $count+$size-1)]
+;
$count+=$size;
}
return [@returnarray];
}
This is untested, so this might "fill-in" your array to fill in the last list. To correct that, you say:
push @returnarray, [splice(@$arrayref,$count, ($count+$size-1<=@$array
+ref)? $count+size-1 :@$arrayref )];
Hmm. There are probably some fencepost errors and such when $size=1 and suchlike, but this should let you play with it. | [reply] [d/l] [select] |
Re: list to LoL
by Maqs (Deacon) on Jun 02, 2000 at 21:53 UTC
|
Below is Adam's modified version. It seemed to be working well
my @a = (1,2,3,4,5,6,7,8,9,10,11,12);
my $n = 4; #parameter
my @lol;
while (@a){
@lol = (@lol, [splice @a, 0, $n]);
$i=$i+$n;
};
print "$lol[2][2]\n"; #for example
/Maqs. | [reply] [d/l] |
|
|
I don't know why you are crediting me with that code, I didn't write it. I see no advantages to it except that it eliminates the need to call reverse(). It also has a useless $i (which $^W doesn't warn you about because you do it twice. Mine has that warning but its easily circumvented - after all you know it isn't a typo). Mine uses $i to avoid steping on the refs (note that @A is both the source and destination in my version). It still destroys @A because splice does that. The only way to preserve the original is make a back up copy.
| [reply] |
Re: list to LoL
by merlyn (Sage) on Jun 06, 2000 at 07:56 UTC
|
How about this for brute force?
my @new;
my $count = 4; # by this many
for (my $i = 0; $i <= $#old; $i++) {
$new[$i / $count][$i % $count] = $old[$i];
}
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |