[Templates] shuffle list vmethod - feature request and proposal
Sergey Martynoff
sergey@martynoff.info
Sun, 12 Feb 2006 03:52:00 +0300
This is a multi-part message in MIME format.
------=_NextPart_000_0020_01C62F87.AE05BD60
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
It is such a common situation when you need to place one or two
random banners, text chunks or links to a web page. Sometimes it
is wiser to get random values in perl code, but often I feel
extreme dearth of 'shuffle' virtual method - particularly when one
of our html coders asks me how to do it in TT.
Yes, I know about Template::Plugin::Shuffle by Tatsuhiko Miyagawa,
but it is rarely preinstalled on hosting servers and based on
another module, Algorithm::Numerical::Shuffle. And I usually feel
too lazy to go and install it myself (and our system administrator
is even more lazy).
So I suggest adding 'shuffle' to standard virtual methods. I have
made quite simple and small realization (independent of any
modules), and propose it to be included in TT 2.15.
Attached files contain test (to be placed in t/vmethods directory)
and patches to lib/Template/Stash.pm and vmethods documentation
source in src/Manual/VMethods.tt2 from separate 'docsrc' package
(I'm not sure in my English, so please read the docs carefully).
Here is it proposed vmethod:
'shuffle' => sub {
my ($list, $limit) = @_;
my @r = \( @$list ); # a list of refs to @$list items
my $i = @$list;
$limit = $i if $limit < 1 || $limit > $i;
return [ map {
my $n = int rand $i--;
( ${$r[$n]}, $r[$n] = $r[$i] )[0];
} (1 .. $limit) ];
},
--
Sergey Martynoff
------=_NextPart_000_0020_01C62F87.AE05BD60
Content-Type: application/octet-stream;
name="shuffle.t"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="shuffle.t"
#=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -*-perl-*-=0A=
#=0A=
# t/vmethods/shuffle.t=0A=
#=0A=
# Testing 'shuffle' list virtual method.=0A=
#=0A=
# Written by Sergey Martynoff <sergey@martynoff.info>=0A=
#=0A=
# This is free software; you can redistribute it and/or modify it=0A=
# under the same terms as Perl itself.=0A=
#=0A=
#=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
use strict;=0A=
use warnings;=0A=
use lib qw( ./lib ../lib ../../lib );=0A=
use Template::Test;=0A=
=0A=
# make sure we're using the Perl stash=0A=
$Template::Config::STASH =3D 'Template::Stash';=0A=
=0A=
test_expect(\*DATA);=0A=
=0A=
__DATA__=0A=
=0A=
#------------------------------------------------------------------------=0A=
# 'shuffle' list virtual method=0A=
#------------------------------------------------------------------------=0A=
=0A=
-- test --=0A=
[% list =3D [ ]; # empty list=0A=
shuf =3D list.shuffle;=0A=
shuf.first;=0A=
shuf.join;=0A=
shuf.size;=0A=
list.shuffle(3).join;=0A=
-%]=0A=
=0A=
-- expect --=0A=
0=0A=
=0A=
=0A=
-- test --=0A=
[% list =3D [ "single_element\n" ];=0A=
list.shuffle.first;=0A=
list.shuffle(1).first;=0A=
list.shuffle(3).first;=0A=
-%]=0A=
=0A=
-- expect --=0A=
single_element=0A=
single_element=0A=
single_element=0A=
=0A=
=0A=
-- test --=0A=
[% list =3D [ 'one' 'two' 'three' ];=0A=
FOREACH i =3D [ 0 .. 5 ];=0A=
"$i:";=0A=
FOREACH a IN list.shuffle(i);=0A=
IF a =3D=3D 'one' || a =3D=3D 'two' || a =3D=3D 'three';=0A=
" ok";=0A=
END;=0A=
END; # /foreach a=0A=
"\n";=0A=
END; # /foreach i=0A=
-%]=0A=
=0A=
-- expect --=0A=
0: ok ok ok=0A=
1: ok=0A=
2: ok ok=0A=
3: ok ok ok=0A=
4: ok ok ok=0A=
5: ok ok ok=0A=
=0A=
=0A=
-- test --=0A=
[% list =3D [ 7 9 11 13 15 17 19 ];=0A=
FOREACH i =3D [ 1 .. 5 ];=0A=
"$i: ";=0A=
n =3D list.shuffle(i).first;=0A=
IF n >=3D 7 && n <=3D 19 && n % 2 =3D=3D 1;=0A=
"odd 7 to 19\n";=0A=
END;=0A=
END;=0A=
-%]=0A=
=0A=
-- expect --=0A=
1: odd 7 to 19=0A=
2: odd 7 to 19=0A=
3: odd 7 to 19=0A=
4: odd 7 to 19=0A=
5: odd 7 to 19=0A=
=0A=
=0A=
-- test --=0A=
[% list =3D [ 1 2 4 8 16 32 ];=0A=
FOREACH i =3D [ 1 .. 4 ];=0A=
"$i: ";=0A=
sum =3D 0;=0A=
SET sum =3D sum + n FOREACH n =3D list.shuffle;=0A=
"$sum\n";=0A=
END;=0A=
-%]=0A=
=0A=
-- expect --=0A=
1: 63=0A=
2: 63=0A=
3: 63=0A=
4: 63=0A=
=0A=
=0A=
-- test --=0A=
[% list =3D [ 1 2 3 4 5 6 7 ];=0A=
s =3D list.join;=0A=
FOREACH i =3D [ 1 .. 270 ];=0A=
shuf =3D list.shuffle;=0A=
IF list.join =3D=3D s && shuf.join !=3D s && shuf.sort.join =3D=3D =
s;=0A=
result =3D "expected";=0A=
END;=0A=
END;=0A=
result;=0A=
-%]=0A=
=0A=
-- expect --=0A=
expected=0A=
=0A=
------=_NextPart_000_0020_01C62F87.AE05BD60
Content-Type: application/octet-stream;
name="shuffle_docs.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="shuffle_docs.patch"
diff -ur docsrc/src/Manual/VMethods.tt2 docsrc-sm/src/Manual/VMethods.tt2=0A=
--- docsrc/src/Manual/VMethods.tt2 Thu Jul 24 18:55:04 2003=0A=
+++ docsrc-sm/src/Manual/VMethods.tt2 Sun Feb 12 03:36:25 2006=0A=
@@ -286,6 +286,22 @@=0A=
In the example, the 'books' list can contains hash references with =0A=
an 'author' key or objects with an 'author' method.=0A=
=0A=
+=3Ditem shuffle=0A=
+=0A=
+Returns a list of elements of a list shuffled in a random order.=0A=
+=0A=
+ [% mylist =3D [ 1, 2, 3, 4, 5 ] %]=0A=
+ [% shuffled =3D mylist.shuffle %]=0A=
+=0A=
+An argument can be provided to specify desired number of items in=0A=
+returned random list.=0A=
+=0A=
+ [% one_random_item =3D mylist.shuffle(1).first %]=0A=
+ [% three_random_banners =3D all_banners.shuffle(3) %]=0A=
+=0A=
+If the argument specified is less than 1 or greater that number of=0A=
+items in a list, it is silently ignored.=0A=
+=0A=
=3Ditem unshift(item), push(item)=0A=
=0A=
Adds an item to the start/end of a list.=0A=
------=_NextPart_000_0020_01C62F87.AE05BD60
Content-Type: application/octet-stream;
name="shuffle_vmethod.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="shuffle_vmethod.patch"
diff -ur Template-Toolkit-2.14a/lib/Template/Stash.pm =
Template-Toolkit-2.14-sm/lib/Template/Stash.pm=0A=
--- Template-Toolkit-2.14a/lib/Template/Stash.pm Thu Feb 2 19:29:07 2006=0A=
+++ Template-Toolkit-2.14-sm/lib/Template/Stash.pm Sun Feb 12 03:46:50 =
2006=0A=
@@ -332,6 +332,16 @@=0A=
return [ splice(@$list) ];=0A=
}=0A=
},=0A=
+ 'shuffle' =3D> sub {=0A=
+ my ($list, $limit) =3D @_;=0A=
+ my @r =3D \( @$list ); # a list of refs to @$list items=0A=
+ my $i =3D @$list;=0A=
+ $limit =3D $i if $limit < 1 || $limit > $i;=0A=
+ return [ map {=0A=
+ my $n =3D int rand $i--;=0A=
+ ( ${$r[$n]}, $r[$n] =3D $r[$i] )[0];=0A=
+ } (1 .. $limit) ];=0A=
+ },=0A=
=0A=
defined $LIST_OPS ? %$LIST_OPS : (),=0A=
};=0A=
------=_NextPart_000_0020_01C62F87.AE05BD60--