Home > Archive > PERL Miscellaneous > November 2007 > making the keys of a hash from parameters collected from a form
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
making the keys of a hash from parameters collected from a form
|
|
|
| Hello everyone:
I have the need to prioritize a number of items from a list and then
print them out in the order in which they were chosen. To be more
specific, I have a list of 12 items and I would like to have the users
indicate which is their first choice, which is their second, etc. up
to 8. I must put the items into a file in the order which has been
prioritized by the user. My thought was to present a form with 12
textboxes, into which they can type the number '1' for their first
choice, the number '2' for their second, etc. Then, when parsing the
form, I could make a hash whose keys are the numbers put into the
boxes, from 1 to 8, with the hash 'values' being the textbox 'names'.
Sorting the hash according to keys would then give me the info I
need. I find, however, that this approach is flawed in that the
collected parameters from the forms are not in the proper format,
apparently, for making into keys. A script or 2 is worth a zillion
words, so I present scaled-down versions of the form and the parsing
script, and if anyone has a solution I sure would like to hear it.
The first script, 'mike.cgi' follows:
#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
print $q->h3("Please indicate your favorite fruit with a '1', and your
second favorite with a '2'. \n");
print $q->h3("Leave the rest blank:\n");
print $q->start_form(-method=>"POST", -action=>"parse.cgi");
print $q->start_form(-method=>"POST", -action=>"getparam.cgi");
print $q->h3(textfield(-name=>'app', -size=>1),"apple");
print $q->h3(textfield(-name=>'ora', -size=>1),"orange");
print $q->h3(textfield(-name=>'lem', -size=>1),"lemon");
print $q->h3(textfield(-name=>'lim', -size=>1),"lime");
print $q->h3(textfield(-name=>'ban', -size=>1),"banana");
print $q->submit, $q->reset, $q->endform, end_html;
exit;
The script that is supposed to make and sort the hash is called
'parse.cgi':
#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
my %hashfruit=(
"param('app')"=>'app',
"param('lem')"=>'lem',
"param('ora')"=>'ora',
"param('lem')"=>'lem',
"param('lim')"=>'lim',
);
my $k;
foreach $k (keys %hashfruit){
print "<P> The key is: <b> $k </b> and the value is <b>
$hashfruit{$key}</b>";
}
end_html; exit;
As you can see, the 'keys' were intended to be the values of
parameters passed to 'parse.cgi', but instead of getting the values (1
and 2), I get as keys the strings 'param(app)' etc. Does anyone
know how to get the actual contents the user typed in so I can use
them as the keys to %hashfruit? Thanks in advance.
Mike
| |
| A. Sinan Unur 2007-11-29, 4:25 am |
| mike <rallabs@adelphia.net> wrote in news:35f36fbc-c724-4df0-a418-
840e48f9895e@n20g2000hsh.googlegroups.com:
> Hello everyone:
> I have the need to prioritize a number of items from a list and then
> print them out in the order in which they were chosen. To be more
> specific, I have a list of 12 items and I would like to have the users
> indicate which is their first choice, which is their second, etc. up
> to 8. I must put the items into a file in the order which has been
> prioritized by the user.
....
> print $q->h3(textfield(-name=>'app', -size=>1),"apple");
A textfield in h3? We're straying off-topic here but that is awful HTML.
> my %hashfruit=(
> "param('app')"=>'app',
> "param('lem')"=>'lem',
> "param('ora')"=>'ora',
> "param('lem')"=>'lem',
> "param('lim')"=>'lim',
....
> instead of getting the values (1
> and 2), I get as keys the strings 'param(app)'
You are specifying the keys as strings in the form "param('app')"
yourself. That's what you told your program to do. How do you expect
anything else to happen?
If, instead, you had used
my %hashfruit=(
param('app') =>'app',
param('lem') =>'lem',
param('ora') =>'ora',
param('lem') =>'lem',
param('lim') =>'lim',
);
the results of the param calls would be stringified.
Of course, you are not performing any sanity checks on the inputs so
this has the potential of becoming problematic. By giving each textfield
a different name, you are making life unnecessarily hard.
Instead, use the same name, say 'rank', for all the textfields. That
way, things like checking that all the ranks are distinct, all the ranks
are numbers etc becomes a much easier operation and you don't have to
make a whole bunch of changes every time you change the list of fruits.
As your scripts are too messy to modify, here is an alternative:
#!perl
use strict;
use warnings;
use CGI qw( -no_xhtml );
my @FRUITS = qw( apple orange lemon lime banana );
my $cgi = CGI->new;
print $cgi->header( 'text/html' );
unless ( $cgi->param ) {
show_form( $cgi );
}
else {
process_form( $cgi );
}
sub show_form {
my $cgi = shift;
my ( $msg ) = @_;
print $cgi->start_html;
if ( $msg ) {
print $cgi->p( $cgi->em( $msg ) );
}
print $cgi->start_form( -method => 'GET' );
for my $fruit ( @FRUITS ) {
print $cgi->p(
$cgi->textfield( -name => 'rank', -size => 1 ), $fruit
);
}
print $cgi->p( $cgi->submit, $cgi->reset ),
$cgi->end_form,
$cgi->end_html;
return;
}
sub process_form {
my $cgi = shift;
my @ranks = $cgi->param( 'rank' );
for my $rank ( @ranks ) {
$rank =~ s/^\s+//;
$rank =~ s/\s+$//;
unless ( $rank =~ /^(\d+)$/
and $rank => 1
and $rank <= @FRUITS
) {
return show_form(
$cgi,
sprintf(
'Ranks must be integers between %d and %d.',
1, scalar @FRUITS
)
);
}
}
my %ranked;
@ranked{ @ranks } = @FRUITS;
unless ( keys %ranked == @FRUITS ) {
return show_form(
$cgi,
'Please fill in all spaces with distinct ranks.'
);
}
print $cgi->start_html,
$cgi->ol(
$cgi->li(
[ map { $ranked{ $_ } } sort keys %ranked ]
)
),
$cgi->end_html;
return;
}
__END__
--
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)
clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
| |
|
| On Nov 29, 12:23 am, "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
> mike <rall...@adelphia.net> wrote in news:35f36fbc-c724-4df0-a418-
> 840e48f98...@n20g2000hsh.googlegroups.com:
>
>
> ...
>
>
> A textfield in h3? We're straying off-topic here but that is awful HTML.
>
>
> ...
>
>
> You are specifying the keys as strings in the form "param('app')"
> yourself. That's what you told your program to do. How do you expect
> anything else to happen?
>
> If, instead, you had used
>
> my %hashfruit=(
> param('app') =>'app',
> param('lem') =>'lem',
> param('ora') =>'ora',
> param('lem') =>'lem',
> param('lim') =>'lim',
> );
>
> the results of the param calls would be stringified.
>
> Of course, you are not performing any sanity checks on the inputs so
> this has the potential of becoming problematic. By giving each textfield
> a different name, you are making life unnecessarily hard.
>
> Instead, use the same name, say 'rank', for all the textfields. That
> way, things like checking that all the ranks are distinct, all the ranks
> are numbers etc becomes a much easier operation and you don't have to
> make a whole bunch of changes every time you change the list of fruits.
>
> As your scripts are too messy to modify, here is an alternative:
>
> #!perl
>
> use strict;
> use warnings;
>
> use CGI qw( -no_xhtml );
>
> my @FRUITS = qw( apple orange lemon lime banana );
>
> my $cgi = CGI->new;
> print $cgi->header( 'text/html' );
>
> unless ( $cgi->param ) {
> show_form( $cgi );}
>
> else {
> process_form( $cgi );
>
> }
>
> sub show_form {
> my $cgi = shift;
> my ( $msg ) = @_;
>
> print $cgi->start_html;
>
> if ( $msg ) {
> print $cgi->p( $cgi->em( $msg ) );
> }
>
> print $cgi->start_form( -method => 'GET' );
>
> for my $fruit ( @FRUITS ) {
> print $cgi->p(
> $cgi->textfield( -name => 'rank', -size => 1 ), $fruit
> );
> }
>
> print $cgi->p( $cgi->submit, $cgi->reset ),
> $cgi->end_form,
> $cgi->end_html;
> return;
>
> }
>
> sub process_form {
> my $cgi = shift;
> my @ranks = $cgi->param( 'rank' );
>
> for my $rank ( @ranks ) {
> $rank =~ s/^\s+//;
> $rank =~ s/\s+$//;
>
> unless ( $rank =~ /^(\d+)$/
> and $rank => 1
> and $rank <= @FRUITS
> ) {
> return show_form(
> $cgi,
> sprintf(
> 'Ranks must be integers between %d and %d.',
> 1, scalar @FRUITS
> )
> );
> }
> }
>
> my %ranked;
> @ranked{ @ranks } = @FRUITS;
>
> unless ( keys %ranked == @FRUITS ) {
> return show_form(
> $cgi,
> 'Please fill in all spaces with distinct ranks.'
> );
> }
>
> print $cgi->start_html,
> $cgi->ol(
> $cgi->li(
> [ map { $ranked{ $_ } } sort keys %ranked ]
> )
> ),
> $cgi->end_html;
> return;
>
> }
>
> __END__
>
> --
> A. Sinan Unur <1...@llenroc.ude.invalid>
> (remove .invalid and reverse each component for email address)
> clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
Dr. A. Sinan Unur: Thank you very much for both these approaches and
their explanations. This may have been too elementary a question for
this newsgroup, but I got a lot of bad advice from the beginners'
group. Thanks again.
| |
| John W. Krahn 2007-11-29, 8:05 am |
| mike wrote:
>
> Dr. A. Sinan Unur: Thank you very much for both these approaches and
> their explanations. This may have been too elementary a question for
> this newsgroup, but I got a lot of bad advice from the beginners'
> group. Thanks again.
Its a *beginners* mailing list, what did you expect? Maybe you should
have asked on the beginners-cgi mailing list instead?
John
--
use Perl;
program
fulfillment
| |
| A. Sinan Unur 2007-11-29, 8:05 am |
| mike <rallabs@adelphia.net> wrote in news:77709129-47b2-42a3-a131-
fcbc069a3034@b15g2000hsa.googlegroups.com:
> Dr. A. Sinan Unur: Thank you very much for both these approaches and
> their explanations. This may have been too elementary a question for
> this newsgroup, but I got a lot of bad advice from the beginners'
> group. Thanks again.
You are welcome. Just a couple of points: First, I appreciate your polite
gesture, but in this group, I am simply Sinan. Second, and more
pertinently, I generally don't use the HTML generation methods provided by
CGI.pm. I would recommend you to look at some of the excellent templating
modules on CPAN (I stick with HTML::Template but there are others) so as
for neater separation between code and presentation. Finally, do read the
posting guidelines for this group, if you read and follow them, you will
find that asking questions (and getting answers) in this group is a much
more rewarding experience than you can get on any beginners list.
Good luck.
Sinan
--
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)
clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
| |
| Dr.Ruud 2007-11-29, 10:06 pm |
| A. Sinan Unur schreef:
> unless ( $rank =~ /^(\d+)$/
> and $rank => 1
> and $rank <= @FRUITS
s/=>/>=/
--
Affijn, Ruud
"Gewoon is een tijger."
| |
| A. Sinan Unur 2007-11-29, 10:06 pm |
| "Dr.Ruud" <rvtol+news@isolution.nl> wrote in news:fio1o8.1hk.1
@news.isolution.nl:
> A. Sinan Unur schreef:
>
>
> s/=>/>=/
Thanks for catching that.
Sinan
--
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)
clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
|
|
|
|
|