Spidy has asked for the wisdom of the Perl Monks concerning the following question:
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Chronologically sort a DBM DB into an array?
by Zed_Lopez (Chaplain) on Oct 06, 2004 at 06:02 UTC | |
I talked to Spidy in the Chatterbox to find out what he wanted here. Here's the situation: he has a dbm file whose keys are the strings returned by localtime and whose values are posts. He wants to find and store the two most recent posts. Spidy, people were confused because we didn't have the context for "sort the hash so that it can be put into an array". "Sorting a hash", alone, doesn't mean anything -- we didn't know whether you meant sorting the hash's keys, or its values, or by what criteria the sort would occur. When you referred to "putting it into an array", we didn't know whether that meant putting the hash's keys in the array, or its values, or a string joining them together, or an arrayref with both the key and value (all of which are things one might want to do.) Now that I think I understand, here's one way to do it:
Now the most recent post is in $recent[1]->[POST] (or $recent[-1]->[POST]) and the next most recent post is in $recent[0]->[POST]. You can make an array of just the posts with: my @posts = map $_->[POST], @recent;Here was my thinking: I want to use each to iterate through the dbm one item at a time, storing only the items I'm interested in, because the file might be very large. I'll have to convert the localtime output to a format I can readily compare. Converting it to Perl's time format, seconds since the epoch, would be one way. Date::Calc probably has something that can do the conversion. I'll need to save both the time and the post as I work through the file -- the time so I can continue to compare it to other values from the file as I work, and the post because that's the info I want in the end. I can use an arrayref like [time, post] to store them together, and put these arrayrefs in an array. I'll keep that array sorted by the time values, so I can easily tell that a given new [time, post] pair has a time < the time in the first array entry, so I know I'm not interested in it and can move on. I want to be able to easily change how many posts I get, in case I change my mind later about only wanting two. I'll call this value num_posts. As I first read the hash I'll just be loading the array with every entry I see, keeping it sorted as I go, until I have num_posts entries, After the number of entries I've stored == num_posts, I know I can ignore any new [time, post] pairs whose time <= the time in the first array entry. For new [time, post] pairs where time > the time in the first array entry, I need to discard the first entry, add the new [time, post] pair, and sort the array. There's a more efficient way to insert a new entry into a sorted list than to just add it and sort the array with Perl's sort, but I expect num_posts to remain small, so I don't think it's worth it to bother pursuing that more efficient way. (I didn't really verbalize all of it to myself in exactly that way, but it's as close as I can come to reconstructing my thoughts in a manner I can share.) BTW, stringified localtime isn't very convenient to work with. If you have the option of using something else, consider it. You could just use seconds since the epoch -- fits in one integer (not much advantage here where you'll be using it as a string), easy to compare (numerically), requires conversion to be human readable. Or you could use SQL's date format, YYYY-MM-DD HH:mm:SS -- a string of 19 characters, easy to compare (as a string,) human readable. | [reply] [d/l] [select] |
|
Re: Chronologically sort a DBM DB into an array?
by pg (Canon) on Oct 06, 2004 at 02:24 UTC | |
It probably would be much more helpful to yourself, if you spend some effort first to have some draft. Then everyone here can help you to enhance it. Have read your home node Spidy. You are only 15, and is now a monk, wow! | [reply] |
by Spidy (Chaplain) on Oct 06, 2004 at 02:33 UTC | |
And then later on...
However, I don't know exactly how I'm supposed to get the entries from the DBM into the array. After that, it's just a simple matter of setting $news1 to $NEWS[0], and $news2 to $NEWS1. I've encountered a stumbling point with the array and sorting though, and have no idea exactly how to do it. and on the age thing, thanks. It took lots of hard work, and more spare time than should be legally possible. | [reply] [d/l] [select] |
|
Re: Chronologically sort a DBM DB into an array?
by mifflin (Curate) on Oct 06, 2004 at 02:34 UTC | |
If you are talking about the AnyDBM_File package then that just ties a hash to a file. If the keys in the file are the epoch time of localtime (the value returned in scalar context) and all you want to do is sort by the keys then here is a loop that will sort the keys...
Update: well, i've just read your followup post and I'm still not sure what you are trying to accomplish. I see you opening the dbm file %NEWS but I don't see you trying to do anything with it. | [reply] [d/l] |