Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Re: changing the printing order of a db

by dga (Hermit)
on Jul 18, 2003 at 22:47 UTC ( #275782=note: print w/replies, xml ) Need Help??

in reply to changing the printing order of a db

Your question is rather vague.

There needs to be some intrinsic bit of information in the data somewhere about how to sort it. To sort in the order it was put in, a sequentially incrementing value placed in the record (or the key) could then be used to sort the records that way later. However, if you want data out for printing in the order originally stored then perhaps a flat file would be more appropriate. Append records onto the end, then by reading the file it comes back out in the order it was put in with no database overhead at all. The hashing methods of a database are optimized for retrieving particular records in an optimized time, not really for putting out an entire data set in a predefined order.

If you use DB_File then there is a DB_RECNO storage method which is for things with a predefined (arbritrary) order which can be fully controlled. If you are sorting by a particular algorithm then DB_File can also use a DB_BTREE to store your records and allow quick access to individual records and also get the records back in your user defined sort order if you want all or part of the entire data set.

A possible answer to your question is that DB_BTREE will sort records in a user defined order based on an algorithm. So you may need only to include as part of the key a way for the sorting algorithm do decide which records go where (the sequentially incrementing value mentioed before may work)

sub Compare { my($k1, $k2)=@_; $k1 cmp $k2; } ... $DB_BTREE->{'compare'} = \&Compare ;

Now DB_BTREE will use Compare to sort the records for storage and retrieval. You can put whatever checks you want into Compare to sort however you want. This only works really cleanly for sorting parts of the keys. Another issue is that if there is a sequence number as part of the key you have to know that to get the key back unless you use the search for the next key >= to the value I am supplying. Another option is to define the compare function so that it knows about the tied hash then it can use parts of the data to do the ordering as in this example.

#!/usr/bin/perl use strict; use warnings; use DB_File; my %hash; tie %hash, 'DB_File', undef, undef, 0666, $DB_BTREE; $DB_BTREE->{'compare'} = sub { my($k1, $k2)=@_; my($v1)=split(' , ', $hash{$k1}); my($v2)=split(' , ', $hash{$k2}); $v1 <=> $v2; }; $hash{key1}='1 , First data'; $hash{key2}='2 , Second data'; $hash{key3}='3 , Third data'; print "A random record (#2): $hash{key2}\n"; #notice no sort on the next line as the records come back in order. foreach my $k ( keys %hash ) { my($n, $v)=split(' , ', $hash{$k}); print "$k: $n: $v\n"; }

This sub will know about the tied hash since it is declared in the scope that the hash is tied. Also the compare needs to be set before any data records are accessed or stored. This uses undef in the spot for the filename giving an in memory only copy of the database which only lives for the duration of the script.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://275782]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (2)
As of 2021-06-19 09:12 GMT
Find Nodes?
    Voting Booth?
    What does the "s" stand for in "perls"? (Whence perls)

    Results (91 votes). Check out past polls.