in reply to Re: rebuilding hashes
in thread rebuilding hashes

I still don't quite understand why 'four' is being repeated. When I delete {2} the key and value of 3/three should be removed and a print with the result:
0 ==== zero 1 ==== one 2 ==== three 3 ==== four
I wrote a note above that goes over why I'm not using an array. This hash in reality isn't being used, this is a test script I setup to see if it would work. I'm actually tying this hash to SDBM and sorting by numbered keys has never been a problem for me using for (grep defined($_), (sort { $a <=> $b } keys %code).

The reason I need to rebuild the hash is because in the admin panel, when they remove a key/value, the user is returned to a menu with back and foward buttons that lets them scroll the data. For the forward button, I increment the key value by one, and the opposite for the back button. BUT, if we have keys 1, 2, 3, 4, 5 and they remove 3, the navigation buttons crash between two and four because it loads 3 which doesn't exist.

Replies are listed 'Best First'.
Re: Re: Re: rebuilding hashes
by duff (Parson) on Feb 02, 2004 at 20:36 UTC
    I still don't quite understand why 'four' is being repeated.

    It's because you still have a key '4' with a value of "four" that you didn't remove from the hash. Perhaps an illustration. Your hash just after you delete the entry keyed by '2':

    0 === zero 1 === one 3 === three 4 === four

    Then you loop over the keys creating new entries. After the first iteration of the loop your hash looks like this:

    0 === zero # this one reassigned 1 === one 3 === three 4 === four

    Second iteration:

    0 === zero 1 === one # this one reassigned 3 === three 4 === four

    Third iteration:

    0 === zero 1 === one 2 === three # this one created 3 === three 4 === four

    Fourth iteration:

    0 === zero 1 === one 2 === three 3 === four # this one reassigned 4 === four

    See?

Re: Re: Re: rebuilding hashes
by stvn (Monsignor) on Feb 02, 2004 at 21:02 UTC

    I still don't quite understand why 'four' is being repeated.
    Abigail-II actually answered this question for you:
    Third, it's showing four twice because you never delete the highest number when re-assigning the numbers.
    I hate to push the issue, but even with your further description, an array sounds like a more appropriate (and less error-prone) data-structure for this problem. Matter of fact you wouldn't even have this problem at all if you used a tied-array for this. It seems to me that your index-keys aren't even really nessecary at all, they are just indecies to the natural order of your list.

    With an array, your HTML-display code could just use a "counter" variable for your page number display rather than the hash-key. Something like this.

    foreach my $page_num (1 .. scalar @pages) { print "<A HREF='script.pl?page=$page_num'>page $page_num</A>"; }
    Then your CGI code would just use the value of "page" as an index to your array, and it will always be guarenteed to be there (assuming they don't reach over the bounds of your array in some way, but thats another problem).

    If this weren't a tied hash i might recommend re-building it from a totally empty (new) hash then you wouldn't need to deal with this problem at all, but i assume the performance penalty on that would be painful.

    -stvn
Re: Re: Re: rebuilding hashes
by ysth (Canon) on Feb 02, 2004 at 21:36 UTC
    As Abigail-II said, you never do anything that would delete the {4} key. Assigning its value to the {3} key doesn't affect {4}.

    A crude way to fix it: After your reassignment loop, delete keys until there are only 1 + (original)$num.

    my $to_delete = keys(%hash) - $num+1; while ($to_delete) { --$to_delete if defined delete $hash{++$num}; }