PDA

Click to See Complete Forum and Search --> : Sorting Arrays


kzatu
Sep 10th, 2008, 04:27 PM
I've seen that PHP has an extensive function list (http://us.php.net/manual/en/ref.array.php) for sorting arrays and either I've missed it 10 time over or they just don't have the one I want.

I have an array that looks like this:
$arr[book01][title]
$arr[book01][author]
$arr[book01][isbn]
$arr[book01][releasedate]
$arr[book01][...]

$arr[book02][title]
$arr[book02][author]
$arr[book02][isbn]
$arr[book02][releasedate]
$arr[book02][...]

and I would like to be able to sort my array by the author. I've tested a few of the functions on the link provided above but most of what I get is it either sorts by

book01, book02, ...

or

book01, title
book02, title

Is there anything I can do here? (thanks in advance)

dclamp
Sep 11th, 2008, 12:14 AM
try ksort (http://us.php.net/manual/en/function.ksort.php)

penagate
Sep 11th, 2008, 02:33 AM
usort will apply a sorting algorithm using a comparison function which you provide. You could define a comparison function which compares the author string of each array element.

function compare_author($book1, $book2)
{
return strcmp($book1['author'], $book2['author']);
}
usort($books, 'compare_author');



try ksort
Did you read the post? The problem is specifically to sort by author, not key.

kzatu
Sep 11th, 2008, 03:23 PM
Yes ksort, as best as I understand it, will only sort the array key which would be the [book01] [book02] elements of the array. Besides, I have tried it, in being hopefull, and it doesn't do what I want it to.

Now Penagate, I'm looking at your example and I'm trying to understand something. I'm not sure how comparing relates to sorting. Also, I will have far more than just 2 books in my array that I want to sort. So I would like to sort all the books in the database by the Aurthor (a-z).

My goal isn't to necessarily sort the array but more to have the data printed to the screen for the user (sorted) so that it is more humanly readable. So if there just happens to be a PHP function that can print sorted rather than sort the array, then that would work to. I'm just tossing this out there in case there happens to be some PHP function that does this. PHP surprises me almost daily.

penagate
Sep 11th, 2008, 07:37 PM
Sorting is based on comparing: the comparison function compares two elements of the array to determine what order they should be placed in. Defining a custom comparsion function allows you to specify how the elements are ordered by the sort algorithm — in this case you want to compare the author subelement of each element. If you try the example I gave you it should do what you want.

Yoosha
Sep 12th, 2008, 12:56 PM
I think this is:
function _Multiple_Sort($Ary_Input, $Int_ScondIndex)
{
if(!is_array($Ary_Input) || !is_integer($Int_ScondIndex) || strlen((string)$Int_ScondIndex) > 255) return((boolean)false);
while(list($Int_FirstIndex) = each($Ary_Input)) $Ary_IndexMap[$Int_FirstIndex]= $Ary_Input[$Int_FirstIndex][$Int_ScondIndex];
@asort($Ary_IndexMap);
$_Ary_Output= array();

while(list($Int_FirstIndex) = each($Ary_IndexMap))
{
if(is_numeric($Int_FirstIndex)) $_Ary_Output[]= $Ary_Input[$Int_FirstIndex];
else $_Ary_Output[$Int_FirstIndex]= $Ary_Input[$Int_FirstIndex];
}

return((array)@array_reverse($_Ary_Output));
}

kzatu
Sep 12th, 2008, 05:40 PM
function compare_author($book1, $book2)
{
return strcmp($book1['author'], $book2['author']);
}
usort($books, 'compare_author');


Wow, this works great and I don't even know how it works. It must be magical. ;) What confuses me is the $book1 and $book2 variables. We start off passing the singular $books() array into usort but that is as far as I understand it. Then it looks though somehow the $books() data gets places into $book1 and $book2 :confused:

penagate
Sep 14th, 2008, 01:17 AM
The comparison function determines how to sort two elements of the array. The sorting algorithm applies the comparison function in order to sort the entire array by doing two elements at a time. The comparison function must return one of three possible values: zero if the two elements are considered equivalent, 1 or more if the first is considered greater than the second, and -1 or less if the converse is true.

Generic comparison functions are supplied which will handle numbers and strings in a predictable manner:
$numbers = array(2, 2, 4, 6, 1, 3, 2, 7, 2, 8, 3, 9, 3, 5, 6, 3);
sort($numbers); print_r($numbers);
rsort($numbers); print_r($numbers);


Sometimes you want to sort using a custom order or by comparing a subelement of an array as you needed. In such cases you can define a custom comparison function, which takes two arguments, each representing an element of the array.

You can see how this function works by dumping its arguments as it is applied.
function comparison_example($x, $y)
{
static $callcount = 0;
echo (++$callcount).': $x = '.$x.'; $y = '.$y.'; diff = '.($x - $y)."\n";
return $x - $y;
}
echo '$numbers has '.count($numbers)." elements.\n";
usort($numbers, 'comparison_example');

This will output the following:
$numbers has 16 elements.
1: $x = 3; $y = 8; diff = -5
2: $x = 1; $y = 3; diff = -2
3: $x = 3; $y = 7; diff = -4
4: $x = 2; $y = 3; diff = -1
5: $x = 3; $y = 6; diff = -3
6: $x = 2; $y = 3; diff = -1
7: $x = 3; $y = 6; diff = -3
8: $x = 2; $y = 3; diff = -1
9: $x = 3; $y = 5; diff = -2
10: $x = 2; $y = 3; diff = -1
11: $x = 3; $y = 4; diff = -1
12: $x = 3; $y = 3; diff = 0
13: $x = 3; $y = 9; diff = -6
14: $x = 3; $y = 3; diff = 0
15: $x = 3; $y = 3; diff = 0
16: $x = 6; $y = 4; diff = 2
17: $x = 6; $y = 5; diff = 1
18: $x = 6; $y = 9; diff = -3
19: $x = 8; $y = 6; diff = 2
20: $x = 7; $y = 6; diff = 1
21: $x = 6; $y = 6; diff = 0
22: $x = 4; $y = 6; diff = -2
23: $x = 5; $y = 4; diff = 1
24: $x = 6; $y = 4; diff = 2
25: $x = 5; $y = 6; diff = -1
26: $x = 7; $y = 9; diff = -2
27: $x = 8; $y = 7; diff = 1
28: $x = 9; $y = 7; diff = 2
29: $x = 8; $y = 9; diff = -1
30: $x = 2; $y = 1; diff = 1
31: $x = 2; $y = 2; diff = 0
32: $x = 3; $y = 2; diff = 1
33: $x = 3; $y = 2; diff = 1
34: $x = 2; $y = 2; diff = 0
35: $x = 2; $y = 3; diff = -1
36: $x = 2; $y = 2; diff = 0
37: $x = 1; $y = 2; diff = -1
38: $x = 2; $y = 1; diff = 1
39: $x = 2; $y = 1; diff = 1
40: $x = 2; $y = 2; diff = 0
41: $x = 2; $y = 3; diff = -1
42: $x = 3; $y = 2; diff = 1
43: $x = 3; $y = 2; diff = 1
44: $x = 3; $y = 2; diff = 1
45: $x = 3; $y = 3; diff = 0
46: $x = 3; $y = 3; diff = 0


For 16 elements this comparison function is called 46 times.

We could alter this to 'unsort' the items.
function random_ordering($x, $y)
{
return rand(-1, 1);
}
usort($numbers, 'random_ordering');
print_r($numbers);



In the code sample which I gave you, we use strcmp to compare the author strings for us.


Hopefully this gives you a better idea of how the sorting functions work.

kzatu
Sep 16th, 2008, 03:22 PM
16 elements, 46 times. Wild. Thank you for the in depth view.

One thing I've noticed with original sorting function you have given me is that it replaces the array keys with a new set of numbers. I was relying on my array keys to stay the same because I use them to uniquely identify each array element. So when a user edits/deletes an item in the array, the process uses the array's key to identify the element to be edited/deleted.

Since I'm reading/writing an INI file, it seems to make sense that my INI's keys should be my array's keys, but maybe I'm going about this wrongly.

If I was using mySQL like I've done in the past, sorting would not be a problem. But I'm finding it an obstacle while using INI.

penagate
Sep 16th, 2008, 07:49 PM
Instead of usort try uasort which will maintain keys.