Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Complex multiple condition sort routine 1

Status
Not open for further replies.

Zhris

Programmer
Aug 5, 2008
254
GB
Hi,

I'm trying to sort data in a particular way:
- Primarily by the users choice.
- Secondarily by "coordinates" (keys 'X' or 'Y' or 'Z').
However, when the user first visits the webpage, because they haven't yet made a choice on how to sort the data, it should be sorted by default by the secondary method only.

I am struggling to achieve the above task because the first condition of the sort routine would be "dynamic" (0 arguements (no user input), 1 arguement (user input), or possibly 3 arguements (default x, y, z)), if you understand what I mean.

Here is some example data:
Code:
my $data = [
	{
		'X' => "1",
		'Y' => "1",
		'Z' => "12",
		'Username' => "Chris",
		'ID' => "1672"
	},
	{
		'X' => "1",
		'Y' => "1",
		'Z' => "14",
		'Username' => "Peter",
		'ID' => "849"
	},
	{
		'X' => "1",
		'Y' => "2",
		'Z' => "2",
		'Username' => "Laura",
		'ID' => "801"
	},
	{
		'X' => "4",
		'Y' => "6",
		'Z' => "8",
		'Username' => "Emily",
		'ID' => "4690"
	},
	{
		'X' => "2",
		'Y' => "9",
		'Z' => "12",
		'Username' => "Daniel",
		'ID' => "7012"
	},
	{
		'X' => "1",
		'Y' => "1",
		'Z' => "4",
		'Username' => "Chris",
		'ID' => "1674"
	}
];

And here is my initial attempt at sorting it, pretending there is user input:
Code:
my %sortroutines = (
	'X' => sub { $_[0] <=> $_[1] },
	'Y' => sub { $_[0] <=> $_[1] },
	'Z' => sub { $_[0] <=> $_[1] },
	'Username' => sub { $_[0] cmp $_[1] },
	'ID' => sub { $_[0] <=> $_[1] }
);

my $sortby = 'Username';

foreach my $row (sort { (     $sortroutines{$sortby}->($a->{$sortby}, $b->{$sortby})     ) || (     $sortroutines{'X'}->($a->{'X'}, $b->{'X'}) || $sortroutines{'Y'}->($a->{'Y'}, $b->{'Y'}) || $sortroutines{'Z'}->($a->{'Z'}, $b->{'Z'})     ) } @$data) {
	foreach my $cell (sort keys %$row) {
		print "$$row{$cell}<br />";
	}
	print "<br />";
}

And my most recent attempt at achieving my overall task (messy):
Code:
my %sortroutines = ();
%sortroutines = (
	'Initial' => sub { $sortroutines{'X'}->($_[0], $_[1], 'X') || $sortroutines{'Y'}->($_[0], $_[1], 'Y') || $sortroutines{'Z'}->($_[0], $_[1], 'Z') },
	'X' => sub { $_[0]->{$_[2]} <=> $_[1]->{$_[2]} },
	'Y' => sub { $_[0]->{$_[2]} <=> $_[1]->{$_[2]} },
	'Z' => sub { $_[0]->{$_[2]} <=> $_[1]->{$_[2]} },
	'Username' => sub { $_[0]->{$_[2]} cmp $_[1]->{$_[2]} },
	'ID' => sub { $_[0]->{$_[2]} <=> $_[1]->{$_[2]} }
);

my $sortby = param('sortby') || 'Initial';

foreach my $row (sort { (     $sortroutines{$sortby}->($a, $b, $sortby)     ) || (     $sortroutines{'X'}->($a, $b, $sortby) || $sortroutines{'Y'}->($a, $b, $sortby) || $sortroutines{'Z'}->($a, $b, $sortby)     ) } @$data) {
	foreach my $cell (sort keys %$row) {
		print "$$row{$cell}<br />";
	}
	print "<br />";
}

My 2nd attempt doesn't work correctly. My question is, how can I ignore the first condition of the sort routine if it isn't needed? If I haven't made myself clear enough, please ask for further details.

Thank you very much in advance for helping.

Chris
 
Thank you Franco,

I was unaware that it would be as simple as that, and would have never of thought to use 0. It worked perfectly.

Chris
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top