Re: reordering lists
by Anonymous Monk on Jan 20, 2004 at 19:57 UTC
|
Don't worry about (re)numbering your photos(bad idea), just keep a list of the order the user wants.
Example:
my %data = 1 .. 10;
my( @data ) = ( 3, 5 , 1, 9 , 7 );
print "$_ => $data{$_}$/" for sort keys %data;
print "---$/";
print "$_ => $data{$_}$/" for @data;
__END__
1 => 2
3 => 4
5 => 6
7 => 8
9 => 10
---
3 => 4
5 => 6
1 => 2
9 => 10
7 => 8
| [reply] [d/l] |
Re: reordering lists
by Roy Johnson (Monsignor) on Jan 20, 2004 at 20:54 UTC
|
just because row 27,895 out of 500,000 was repositioned to slot 3, now 499,998 rows will have their id recalculated.
Not so. Only the ones between the old and new positions need to be recalculated.
sub move {
my ($from, $to) = @_;
my $temp = $row[$from];
if ($from < $to) {
for ($from+1..$to) {
$row[$_-1] = $row[$_];
}
}
else {
for (0..$from-$to-1) {
$row[$from-$_] = $row[$from-$_-1];
}
}
$row[$to] = $temp;
}
The PerlMonk tr/// Advocate
| [reply] [d/l] |
|
|
yes, you are right. My bad. Of course, in the worst case (if the last slot is repositioned to the first slot) all the rows will have to be recalculated.
What you are suggesting is what I had resigned myself to doing with the database. My guess is, DBI should be fast enough to not worry about it.
Its just that it seems like an inelegant method. Hence, my question in the first place.
| [reply] |
Re: reordering lists
by Roger (Parson) on Jan 21, 2004 at 01:33 UTC
|
I think it's rather a matter of design. I would prefer to keep the code as simple as possible: do sorting at database level, and keep the (business) logic as simple as possible.
Assume that your tables are defined some what like this -
| house_id | kitchen_id | bathroom_id |
| 1 | 101 | 103 |
| 2 | 102 | 104 |
| image_id | image_name | date_entered |
| 101 | image01.jpg | 2004/01/02-11:30 |
| 102 | image02.jpg | 2004/01/02-13:30 |
| 103 | image03.jpg | 2004/01/03-12:30 |
| 104 | image04.jpg | 2004/01/05-13:30 |
Then I would introduce a hash table of SQL statements in the code, indexed by the alias of sorting order. The following code is not tested, just an idea on how this problem may be tackled.
my %SQL = (
order_by_date => 'select image_name from image
where house_id in (
select kitchen_id, bathroom_id
from house where house_id=?
)
order by image_date',
kitchen_first => 'select image_name from image
where image_id =
( select kitchen_id, bathroom_id
from house where house_id = ? )',
bathroom_first => 'select image_name from image
where image_id =
( select bathroom_id, kitchen_id
from house where house_id = ? )',
);
....
$sth = $dbh->prepare( $SQL{order_by_date} );
....
$sth = $dbh->prepare( $SQL{kitchen_first} );
....
| [reply] [d/l] |
Re: reordering lists
by hardburn (Abbot) on Jan 20, 2004 at 20:14 UTC
|
$ perl -le '
$, = ", ";
@a = (0 .. 20);
print @a;
@a[2,1] = @a[1,2]; # Magic line
print @a;'
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20
0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+2
For more complex things, you might need splice.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
: () { :|:& };:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
Re: reordering lists
by injunjoel (Priest) on Jan 20, 2004 at 20:02 UTC
|
Greetings all,
I would suggest adding an int column to your images table. This way you can store the display order with the images.
This would require that you program in some logic to allow the user to re-order the display of the images.
You could also designate a image type in your table. Something like img_type ENUM('front-exterior','kitchen','bathroom','etc'); but this has the drawback of not being very flexible, say for instance someone has 15 images of the bathroom. It does however allow you to program the default behavior for these images (your kitchen before bathroom issue).
Personally I would add both. This way you have an type designation ('kitchen','bathroom','etc') and a display_order for each image. Just a thought, I hope that helps.
| [reply] [d/l] |
Re: reordering lists
by jonadab (Parson) on Jan 21, 2004 at 01:19 UTC
|
Are you really using a database? If you're using a real
database, it undoubtedly has support for indexing more
than one field in a table. That is, besides the primary
key field, you can have auxiliary key fields. So, add
a secondary key field that stores a number. Start out
with all the numbers being multiples of ten (just like
line numbers on old BASIC programs) so that you can
insert several records in between before you have to
renumber your index. Moving a record from the middle
out to the beginning or end, of course, is easy: you
just leave a bigger gap where it came from, no problem.
Then you write a script that uses idle time or off
time to look for places where the numbers are bunched
together and renumber some records to pull them apart.
The only time you take a performance hit is when you
need to insert a record between two that already have
adjascent numbers, and even then you only have to
renumber enough records to fit it in, and let the
background renumberer worry about smoothing out
the distribution later.
If the list isn't large enough to warrant a full
database, just use splice.
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
| [reply] [d/l] |
Re: reordering lists
by punkish (Priest) on Jan 20, 2004 at 20:33 UTC
|
I am adding a general comment on the 3 replies thus far. It seems that splice/slice might be a solution, but I have to figure out how to implement that in a database.
Adding another column to the table to store the sort order may be an idea, but changing the sort order of any one element will entail recalculating the sort order of the all subsequent elements in the table. This is the original "thorny" problem that I am trying to circumvent.
One way I thought up would be to create a sort order that is not sequential but jumps by an increment of, say, 100 or 1000... the way we used to number lines in BASIC... to avoid renumbering lines in case a line has to be moved. So, I would create a column for storing the sort order, but instead of storing 1, 2, 3... I would store 1000, 2000, 3000... Then, if the element 45 with the sort order value 45000 had to be repositioned at slot 3, I would just renumber its sort order value to 2500 (leaving space on both sides, before/downto 2000, and after/upto 3000 without having to recalculate any other element.
Of course, this is inelegant as heck, and is not scalable. But might work.
Any thoughts?
Btw, I am also reading up on linked lists in the hope they may offer some salvation. | [reply] |
|
|
I am also reading up on linked lists
This seems like it might be the way to go. A linked list, based on my understanding, is just a bunch of items that have pointers, aka links, to their neighbors. Perhaps one could use a table with columns THIS_ID, PREV_ID, NEXT_ID. Then only a few columns need to be changed in order to remove an item, add a new item, or move an item to a different location.
The problem with this approach, as I see it, is you then have to step through the whole thing sequentially in order to build your final ordered list. Perhaps there are some techniques to avoid this that I'm unaware of (I do not have a computer science background; I'm just a long-time amateur programmer).
If there are any other ideas, I'd love to hear them. It's always an education. 8^)
Update: to clarify a bit, I should have mentioned that I agree with some of the monks who say the order should be separate from the definition of the images. In other words, you might have one table called IMAGES with columns IMAGE_ID, IMAGE_NAME, IMAGE_SIZE, IMAGE_COMMENTS then a separate table named IMAGE_ORDER with the THIS_ID, PREV_ID, NEXT_ID columns.
| [reply] [d/l] [select] |
|
|
| [reply] |