Multi-dimension array value sorting in PHP
I am building up an array with a set of database fields with information about table, actual field name and descriptive field name as a multi-dimensional array. Here is what it currently looks like:
$Fields['User']['ID'] = "User ID";
$Fields['User']['FirstName'] = "First Name";
$Fields['Stats']['FavouriteOrder'] = "Favourite Item Ordered";
$Fields['Geographic']['Location'] = "Current Location";
$Fields['Geographic']['LocationCode'] = "Current Location Code";
Okay, this is fine, but I am piping this into a system that allows exporting of selected fields, and in the end I want to foreach() through the different levels, extract the data and then ultimately have all the descriptive fields to be displayed sorted alphabetically using their descriptive name. So ultimately in the order: Current Location, Cur开发者_如何学Crent Location Code, Favorite Item Ordered, First Name then User ID - obviously keeping index associations.
I can't use usort() and I can't use array_multisort()... or maybe I can and I just don't know how. usort() seems to need a key to sort by, but I have variable keys. array_multisort() just seems to do the same as sort() really.
This is for a 2D array only. Not the most elegant piece of code I've written, but it works...
foreach($Fields as $key=>$var) {
ksort($var);
$Fields[$key]=$var;
}
ksort($Fields);
Let me rather give a real-life data example, as opposed to fake data because the fake data nearly confused me. So, fake data is commented.
/*
$Fields['User']['ID'] = "User ID";
$Fields['User']['FirstName'] = "First Name";
$Fields['Stats']['FavouriteOrder'] = "Favourite Item Ordered";
$Fields['Geographic']['Location'] = "Current Location";
$Fields['Geographic']['LocationCode'] = "Current Location Code";
*/
$Fields['Product']['ReferenceNumber'] = "Product Reference Number";
$Fields['Product']['Halaal'] = "Halaal Status";
$Fields['Product']['Kosher'] = "Kosher Status";
$Fields['Product']['KosherType'] = "Kosher Type";
$Fields['Product']['CuringSalts'] = "Curing Salts Status";
$Fields['Product']['ProductVisibility'] = "Product Visibility";
$Fields['Product']['ProductStatus'] = "Product Status";
$Fields['Product']['PackBarCode'] = "Barcode";
$Fields['Product']['ProductDescription'] = "Product Description";
$Fields['Pack']['PackSize'] = "Pack Size";
$Fields['Pack']['PackSizeNumeric'] = "Numeric Pack Size";
$Fields['Allergens']['ContainsNuts'] = "Product Contains Nuts";
foreach ($Fields as $key => $value) {
ksort($value);
$Fields[$key] = $value;
}
ksort($Fields);
I'm having one of 'those' Fridays... print_r($Fields) reveals that the keys are being sorted and values are associated, but it's still sorting by the keys and not the end value.
It's almost like i need a reverse sorting system which checks all values first, sorts them and then says 'okay where do you belong ... ah you belong to FieldX in Table Y'
I was hoping there was a sneaky clever way to do it, perhaps there is, but I guess I'll write a function to parse through the data, write a reversed array and then re-write the original in value-order. Hectically inefficient, but it'll do.
Still open to better suggestions though!
I literally had to work this out yesterday for a project I was working on - here's my code:
Resource array looks like this:
$resource[$count]['title']
$resource[$count]['filepath']
$resource[$count]['filename']
$resource[$count]['taxonomy'][0]
A couple of sort functions to sort by title ASC or DESC
function compare_asc($a, $b) {
return strcmp($a['title'], $b['title']);
}
function compare_desc($a, $b) {
if ($a['title'] == $b['title']) {
return 0;
}
return ($a['title'] > $b['title']) ? -1 : 1;
//return strcmp($a['title'], $b['title']);
}
And finally use usort to do the dirty before you loop through $resource and output whatever it is you need.
usort($resource, "compare_asc");
Okay, it's not elegant at all. So I don't encourage using this and will look for a better way down the line. But here's the solution I've got that works with the examples above and below.
Unfortunately, the way I want it to be, the array HAS to contain a preceding 'ordering' number so, I suppose it's a fail on my part from the very beginning. But it works now.
$TempDescArray = array();
$TempFieldArray = array();
$TempTableArray = array();
$Pointer = 0;
foreach ($Fields as $Table => $FieldsArray) {
foreach ($FieldsArray as $Field => $Description) {
$TempDescArray[$Pointer] = $Description;
$TempFieldArray[$Pointer] = $Field;
$TempTableArray[$Pointer] = $Table;
$Pointer++;
}
}
asort($TempDescArray);
$Fields = array();
$Pointer2 = 0;
foreach ($TempDescArray as $Pointer => $Description) {
$Fields[$Pointer2][$TempTableArray[$Pointer]][$TempFieldArray[$Pointer]] = $Description;
$Pointer2++;
}
精彩评论