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

I'm trying to produce a random image link display (like a banner rotator). My idea was to keep the information inside of my database like $db{$imagetitle} = $urltolinkto; and make an array out of it (using || as a separator).

Is there a better method to doing this? Better = easier to maintain but not harder to understand.

Thanks everyone.

my @imagearray; # array for everything in database foreach (keys %db) { push(@imagearray, "$_||$db{$_}"; # $imagetitle || $url } my @shuffled_array = shuffle(@imagearray); # shuffle the array my($name, $url) = split("||", "$shuffled_array[0]"); # split array on +|| print qq(<a href="$url"><img src="/images/$name"></a>);


"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: converting hash to shuffled array
by Abigail-II (Bishop) on Sep 11, 2003 at 18:03 UTC
    That's quite inefficient. Why not something like:
    my $key = (keys %db) [rand keys %db]; print "<a href = '$db{$key}'><img src = '/images/$key'></a>";

    Abigail

      I gotta ask - where might be an explanation of the implicit int() within the subscripting []'s?   It's so beautiful and dreadful at the same time.

      I've seen something like this done before, a long time ago, but I guess I just accepted it as 'magic'.   I was reminded on CB that a FP number wouldn't make any sense as a subscript and so the DWIMish gnomes happily fixed the value.   But sometimes I get this panicky feeling that if the magic isn't documented, it'll run away when I'm not looking.

Re: converting hash to shuffled array
by tcf22 (Priest) on Sep 11, 2003 at 18:04 UTC
    You are already looping through the hash, just use rand() to pick a random element out of the hash.
    my $r = int(rand(keys %db)); my $i = 0; foreach (keys %db) { if($r == $i){ print qq(<a href="$_"><img src="/images/$db{$_}"></a>); last; } $i++; }

    - Tom

Re: converting hash to shuffled array
by Enlil (Parson) on Sep 11, 2003 at 18:09 UTC
    On a quick note doesn't split "||" split on every space (update:i.e. the mysterious spot between each character)?. I believe you have to replace the "||" (pipes are special in regular expressions) for "\|\|". Another way to do what your doing (untested):
    use strict; use List::Util qw/shuffle/; my @imagearray = shuffle keys %db; my ($name,$url) = ($imagearray[0],$db[$imagearray[0]); print qq(<a href="$url"><img src="/images/$name"></a>);

    -enlil

Re: converting hash to shuffled array
by davido (Cardinal) on Sep 11, 2003 at 18:06 UTC
    If you don't mind throwing a little memory at it, you could do it this way, and still preserve the usefulness of the original hash.

    my @keybucket = keys %db; shuffle (@keybucket); foreach my $key ( @keybucket ) { print qq(<a href = "$key"><img src="/images/$db{$key}"</a>); }

    I took some liberties with the general flow and variable names used in this snippet. You'll have to massage it to fit your needs. But the idea is why coerce the hash into an array of unnatural character when you can keep the hash and just make a shuffled list of its keys.

    This approach has merit in a situation where you want to ensure that you are holding the entire shuffled deck, so to speak, so that you can guarantee uniqueness as you draw additional items from it. If you're only interested in one random item, the creation and shuffling of an array is overkill. However, if you want to draw multiple random items, and make sure not to draw the same one twice, the array of hash keys approach is good because you can just keep shifting items off the top of the stack one by one, or even take an array slice of the stack if you need multiple items.

    If you use such an approach (to solve this or other problems) you should take care to always update the array of keys if you've added another item to the hash.

    Dave

    "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

Re: converting hash to shuffled array
by atcroft (Abbot) on Sep 11, 2003 at 18:10 UTC

    Would something like this (untested) work instead:

    my @imagearray = shuffle(keys %db); print qq(<a href="$db{$imagearray[0]}"><img src="/images/$imagearray[0 +]"></a>);

    Basically, would it work to just put the image titles (the keys to %db, in your code) in the array, shuffle it, then refer back to the hash element whose image title (key) is in element 0, rather than trying to put the whole thing in then split it later? Just wondering...

Re: converting hash to shuffled array
by BrowserUk (Patriarch) on Sep 11, 2003 at 19:47 UTC

    If you only want random and not shuffled

    my( $name, $url ) = do{ my @pair; # updated!! Whoops! @pair = each %db for 0 .. rand keys %db; @pair; }; print qq(<a href="$url"><img src="/images/$name"></a>);

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      Of all the wonderful responses I think this is the easiest one for me to understand and implement into my script. I do have a question or two about it and was wondering if you could help me figure them out.

    • Why is there a my $pair? I only see it being used in that one statement.
    • Why is there a @pair at the end when the previous line is giving it a value?

      Thanks for your help everyone! I've noticed most of your scripts are very similar in nature which makes it easier. I didn't know you could do a @array = keys %db, that must be a lot easier on the server instead of doing a foreach loop.

      "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

        Why is there a my $pair? I only see it being used in that one statement.

        Um! Cos I made a mistake! It should be @pair and now is:)

        Why is there a @pair at the end when the previous line is giving it a value?

        The previous line loops a random number of time setting the @pair to succesive key/value pairs from the hash.

        Once the loop stops, the last statement becomes the return value for the do block, and so the last key/value pair assigned to the array @pair, get assigned to the variables $name and $url.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: converting hash to shuffled array
by Cody Pendant (Prior) on Sep 11, 2003 at 22:40 UTC
    I just give my images numeric names, and generate a random number between 0 and 100 to display one -- 0.gif to 100.gif.

    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print