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

The chat portion of this script works (it's on message 1400) and the count keeps working. This is the majority of the log file and this does NOT work. It seems to freeze at 100 messages every time. This is to say, it'll display all messages properly until around 100 and then it stops changing.

The script that writes to the database originally works just fine, it only displays 10 keys at a time but it works perfectly at 1400+ messages. Why is this not working to display the last 100? It just locks up at about 100.

print header, start_html('DB printing'); print "<table>"; for (grep defined($_), (keys %db)[-1 .. -100]) { . . .

Replies are listed 'Best First'.
Re: printing last 100 keys from hash
by DrHyde (Prior) on May 21, 2004 at 07:37 UTC
    (keys %db)[-1 .. -100] has a few problems.

    .. only works in ascending order, so you need to replace it with reverse -100 .. -1. But ...

    The order of the data returned by keys is effectively random. So all that will give you is an unpredictable selection of 100 keys from the hash.

    If you want the last 100 keys to be created or updated, then you're going to need to use some variety of tied hash. I suggest looking at Tie::InsertOrderHash and Tie::Hash::Indexed.

      Why would this work when I use -10 .. -1 then? This works fine showing the latest 10 posts in the other script and the code is exactly the same except the numbers.

      I tried for (grep defined($_), (sort keys %db)[-100 .. -1]) { like someone suggested and instead of printing 100 messages that don't change, it doesn't print anything.

      Are there any modules that will make hashes use insertion order that comes with the Perl package? Or would I have to go out and install one?

      Also, in the main program I am saving hash keys as numbers. I do a foreach(keys %db) { $num++} then when I save messages to it, I save by $db{$num} = ... . So whether I use a module or not, if I sort by key it should work since it's all numbers. But it doesn't work *shrugs*
Re: printing last 100 keys from hash
by guha (Priest) on May 21, 2004 at 10:49 UTC

    I can see two issues with your example.

    1. As DrHyde says the order of a hash is not defined the way one expects. You will have do an explicit sort, depending of the value of your keys, the default sort may suffice or you may have to create an appropriate sort function.

    2. Your use of the Range operator is not correct. The right argument must be larger than the left.

    This should lead to something along the lines of

    for (grep defined($_), (sort keys %db)[-100 .. -1]) {
    HTH

Re: printing last 100 keys from hash
by eric256 (Parson) on May 21, 2004 at 15:12 UTC
    If you are concerned about the order of the messages then it would make more sense to store them in and array than in a hash. It maybe that you lookup these messages by some other value in which case you may want a hash. In that case you could use an array of keys in the order they should appear. Then instead of doing keys on the hash you just grab the last 100 elements of the array.

    ___________
    Eric Hodges