...

View Full Version : sort array by multiple values



PaulC2K
12-07-2008, 07: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.

Thanks in advance,
PC2K

ptmuldoon
12-07-2008, 08: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, 09: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, 10: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, 12: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, 04: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, 05: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++;
// data ready for use
}

For a while i couldnt quite understand why i was doing the foreach loop, or what the extended version was doing (standard seemed reasonable) and while it was working and i'd labelled things better for me to follow things it took me a while to realise it was creating new arrays for each 'catagory' (i dont know the correct terminology ~75% of time :p) to then sort them, so that makes sense to me now at least.

I've been able to enter time & lap penalties to the penalties table and its done what its needed to as far as i can tell. Im guessing the comment about having trouble identifying which table things are from isnt so important in my case, the initial array is building new data which is for only for sorting and displaying purposes, the persons name and a reference id (result_id) are there to pull additional data when needed, so afaik its working as i hoped.

Thanks for the explanation on the => i've always tried to avoid arrays because they easily confuse me and using a db is far easier to work with for me at least. Some of that makes sense to me, but as i mentioned im clueless on a lot of the correct terminology for things which doesnt help when trying to explain or even track down the answers on php.net etc, ive only picked up things as ive gone along. My code is largely 'baby code', probably really long winded ways of writing things but it makes sense to me and that works for me :o



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum