...

# sort array by multiple values

PaulC2K
12-07-2008, 08:22 PM
Hi,

Im trying to figure out if its possible to sort an array by multiple values, in the same manner that you would with mysql, ie 'order by X asc, Y desc' etc

I have 2 tables, one table has the original values which i want to stay original, then the 2nd table has a modifier for 2 values.
I need to get both original values and then include the modification value onto that, then i need to build my array up and ask it to sort by the 1st value, then by a 2nd value.

I've never liked arrays and i dont know of a variation of 'sort' which will allow me to do this, so im hoping its possible and someone can explain how thats done.

what i have at the moment as an example:

\$my_array[\$a]['value1'] = \$myrow['value1'] + \$myrow2['value1'];
\$my_array[\$a]['value2'] = \$myrow['value2'] + \$myrow2['value2'];
\$my_array[\$a]['value3'] = \$myrow['value3'];
\$my_array[\$a]['value4'] = \$myrow['value4'];
\$a++;

So im looking for something like sort('value1' asc, 'value2' desc)

Any ideas?? Right now my only thought is to instead write the modified data to a table, use it to correctly order the data, display it, then have it delete the table once its finished displaying it... and surely theres a better alternative than that.

PC2K

ptmuldoon
12-07-2008, 09:45 PM
There's plenty of sorting array options

http://us3.php.net/sort will sort ascending

Look at the other sorting options too such as rsort, arsort, etc.

PaulC2K
12-07-2008, 10:12 PM
yeah, ive been through the obvious ones, that was the first thing i did, but they all seem to be based on 1 value, not multiple with each by different order asc/desc type etc.

since posting i found array_multisort() and looks like it would work, however im yet to understand it fully to get the required results, and even the examples ive seen which look similar to what i have give an error on the array_multisort line so they've been little help.

Fou-Lu
12-07-2008, 11:54 PM
You should be able to get SQL to do this for you.
To do this with PHP, you'll need to be able to differentiate the two resulting arrays. Either by creating two arrays (one with the data from the first, one with data from the second), which can be filtered by the array_multisort, or you create a multi-dimensional array differentiating the two results and apply a user sort function (u*sort) with a comparative callback, or once again by using array_multisort on the respective inner arrays.
You can even use something like array_filter to perform this task, but you need to be tricky with it.
The key to any of these methods is to differentiate the results. This can only be done with multiple arrays, multi-dimensional arrays, consistent associative key naming or objects. If results are chunked into a single resultset, its difficult to tell which results are from which table.

PaulC2K
12-08-2008, 01:27 AM
Ive managed to figure out the array_multisort function, it wasnt so much that function which was the problem but the formation of the data it was being given.

Anyone able to tell me what => means, it crops up in arrays all the time but i cant say i know what that specificly means. Im guessing its something like 'equals this', but if thats the case why wouldnt just '=' do?
My php/sql book makes no attempt to explain it within the arrays section, it just starts slapping them in there assuming you already know... wonderful :rolleyes:

Fou-Lu
12-08-2008, 05:27 AM
Think of it as 'associated with'. The biggest difference from a usability standpoint with the '=' sign is that you cannot assign a value to a primitive value. That is:

'mval' = 'value'; // Either can be any primitive

is illegal. However, from an array, => is the associative access for it:

\$aVals = array(
'test' => 'i am test';
);

print \$aVals['test'];

Sets up the array \$aVals with associated keys. Index of 'test' refers to the value associated with 'test', in this case 'i am test'.
PHP doesn't actually handle arrays. It has a built in hash map utility mapping the primitive array keyword to a more advanced hashmap type (which of course doesn't actually exist in PHP either). Its more of a HashMap<Object, Object> declaration for those that are more used to Java/C# syntax.
=> is only seen in arrays. You will see it as often in the foreach syntax foreach (\$arr as \$key=>\$val). Don't confuse this with the -> operator which is used to access methods and properties of an object relative to \$this (lol, where \$this = \$object, clear as mud? Good).

Anyway, sorry did you get this solved then? Like I was saying before, you'll have troubles unless you can identify which of the records belong to which of the tables. There are a few approaches to this, one is to use more than one query (simplist), and another is to use a method that will identify which table you're using as a resulting field from you're resultsets.

PaulC2K
12-08-2008, 06:08 AM
Yeah, i managed to get it working just how i needed it to.

The script is for a sim racing site ive been working on, and i needed to take an original race result and then add any penalties which were later applied.
I wanted to keep the original data in its original state, and not modify it perminantly for safety & ease of modification. Previously i was just sorting straight from the database by laps done then time finished, but penalties could impact on those values, making them inaccurate.

I went with: (slightly modified to remove junk)

{
// removed mysql_fetch data etc
\$modified_order[] = array(
'laps' => \$modified_laps,
'time' => \$modified_time,
'lfsname' => \$lfsname,
'result_id' => \$result_id);
}

foreach (\$modified_order as \$key => \$label)
{
\$sort_laps[\$key] = \$label['laps'];
\$sort_time[\$key] = \$label['time'];
\$sort_lfsname[\$key] = \$label['lfsname'];
\$sort_result_id[\$key] = \$label['result_id'];
}
array_multisort(\$sort_laps, SORT_DESC, \$sort_time, SORT_ASC, \$modified_order);

\$i='0';
while (\$i <= \$key)
{
\$lfsname = \$modified_order[\$i]['lfsname'];
\$modified_time = \$modified_order[\$i]['time'];
\$modified_laps = \$modified_order[\$i]['laps'];
\$res_id = \$modified_order[\$i]['result_id'];
\$i++;