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

This might be a little hard to explain or for anyone to understand, but I need to count each key in a database and foreach set of 20 keys print something unique for that set. Then at the end, if we have more than an even set of 20 keys (let's say we have 41 keys), the surpluss should be treated as if it were a full set of 20.
$amount_of_keys = keys %upload; # for all instances of $amount_of_keys % 20 { # print qq(<a href="url#.html></a>); # if there is a remainder that isn't % 20 { # print qq(<a href="url#.html></a>); } }
The # in the url needs to be incremented for each set of 20 (or the surplus). Let's say there are 78 keys in the database.
keys 1-20 would print url1.html keys 21-40 would print url2.html keys 41-60 would print url3.html keys 61-80 would print url4.html (even though we don't have 80 images, + we have a surplus and still need to generate a url for it).
If this doesn't make any sense, please PM me and I'll try to find a different way to explain this. Thanks for taking the time to look at this.

"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: hash keys, %
by blokhead (Monsignor) on Jul 29, 2003 at 00:31 UTC
    I'm not quite sure what you mean by having a unique URL for each group of twenty. Do you want to generate URLs to pass twenty things at a time to some script?
    my @keys = sort keys %hash; my $group = 0; while (my @group = splice(@keys, 0, 20)) { ## generate url from stuff in @group $group++; ## maybe something like this if the items ## are all safe (\w characters): my $url = 'script.cgi?' . join '&', map { "x=$_" } @group; print qq(<a href="$url">group # $group</a><br>\n); }
    Even if this isn't quite what you had in mind, maybe the while( .. splice .. ) loop will be a good starting place. The loop condition won't fail until @group gets 0 items, and will still iterate even if @group gets less than 20 the last time through the loop.

    Update: if the links only depend on the number of keys, and not the keys themselves, then the number of URLs to print is simply ceil( (keys %hash) / 20 ). ceil simply rounds up, you can import it from the POSIX module.

    blokhead

      I'd like to thank you two for (blokhead and cleverett) for helping with this tricky problem. Of the two methods posted, I went with blockhead's because it looks a lot easier to understand (even though I won't understand fully what's going on until I take a look at splice in a few minutes).

      The code I used is

      my @keys = sort keys %upload; my $group = 0; while (my @group = splice(@keys, 0, 20)) { $group++; my $url = "http://sulfericacid.perlmonk.org/gallery/galleryprint2.pl"; print qq(<a href="$url?page=$group">$group</a><br>\n); }
      What exactly is being stored in @keys? The total of keys from the hash or all the key/value information from the hash and using this as an easier method to count each of them?

      Thanks again for all your help! If you want to see why I needed this, http://sulfericacid.perlmonk.org/gallery/galleryprint2.pl.

      "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

      sulfericacid

        splice(@keys, 0, 20) removes the first 20 items from the array @keys, but almost as important, it also returns the items it removed. So it's like using shift on a larger chunk. You can use splice to simulate push, pop, shift, and unshift, as well as insert and remove items from the middle of an array. Of course, the man page for splice goes over all this in detail, but it's often useful to think of a splice operation in terms of those 4 basic list operators.

        But I would suggest not even using this loop, since you never actually seem to use the stuff in @group that you splice off. You only seem to be interested in the number to print out, so you could just as easily do this:

        use POSIX 'ceil'; my $url = "http://..."; my $num_pages = ceil( (keys %hash) / 20 ); print qq(<a href="$url?page=$_">$_</a><br>\n) for 1 .. $num_pages;
        Even if you do use this method, you should still get familiar with splice!

        blokhead

Re: hash keys, %
by cleverett (Friar) on Jul 29, 2003 at 00:41 UTC
    use array slices in combination with hash slices, thusly:
    use strict; my @keys = keys %hash; my $span = 20; my ($page, $last_page) = (0, int($#keys / $span)); while ($last_page > 0 and $i < $last_page) { make_page($page, @hash{@keys[$i * $span .. (++$i) * $span - 1]}); } make_page($last_page, @hash{@keys[$last_page*span .. $#keys]});
      heh, I forgot about splice ...