array_multisort question

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

array_multisort question

Post by victorsk »

Hello,

I was just wondering if there is a way to use array_multisort to sort by two criteria at the same time. What I have is 14 arrays containing tour information. I use array_multisort to sort by hotel rating like this:

Code: Select all

array_multisort($starRating, $imageUrl, $hotelName, $departureDate, $returnDate, $tripDuration, $packageCode, $tourOperator, $mealPlan, $roomOccupancy, $outputIndex, $sourceCurrency, $supplierLink, $totalPrice);
Now I need to take the result and sort $totalPrice so for each sorted star rating the price is presented from highest to lowest. What I did initally was copy the resulting multisort by star rating into a 2D array, then split into individual "sub-arrays" with their own ratings, then sort them in a loop. But that turned out very inefficient and didn't work too well.

I think it's possible to specify in array_multisort() additional sorting criteria, and I tried it like this:

Code: Select all

array_multisort($starRating, SORT_ASC, $imageUrl, $hotelName, $departureDate, $returnDate, $tripDuration, $packageCode, $tourOperator, $mealPlan, $roomOccupancy, $outputIndex, $taxes, $sourceCurrency, $supplierLink, $totalPrice, SORT_NUMERIC, SORT_ASC);
So here I am trying sort by star rating and by total price simultaneously. But that doesn't seem to work. Would anybody please suggest the correct use of array_multisort() so I can accomplish my task?

Your help, as always, will be greatly appreciated.
Thank you.
Victor.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

I had found this function in the user comments a few years ago that does what you want. It is ugly, and it uses eval() which I am not fond of, but it will do what you want (I have used it myself and it does work):

Code: Select all

<?php
function array_multi_sort() 
{
    //coded by Ichier2003 
    // taken from php.net
    // http://us4.php.net/manual/en/function.a ... tisort.php
    $args = func_get_args(); 
    $marray = array_shift($args); 

    $msortline = "return(array_multisort("; 
    $i=0;
    foreach ($args as $arg) 
    { 
        $i++; 
        if (is_string($arg)) 
        { 
            foreach ($marray as $row) 
            { 
                $sortarr[$i][] = $row[$arg]; 
            } 
        } 
        else 
        { 
            $sortarr[$i] = $arg; 
        } 
        $msortline .= "\$sortarr[".$i."],"; 
    } 
    $msortline .= "\$marray));"; 

    eval($msortline); 
    return $marray; 
}
?>
Usage:

Code: Select all

<?php
$myArray = array_multi_sort($myArray, 'field1', SORT_ASC, 'field2', SORT_DESC, 'field3', SORT_ASC);
?>
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Hi,

Thank you so much for replying. I had a solution yesterday and wanted to post it but something was wrong with connection. I have found a solution which has made my application work a bit faster (I think) because I reduced the number of arrays from 14 to just 1. Because of my inexperience with PHP I didn't know this could be done. But it is:

What I did was:


1. Create an array with unique keys for each of its elements:

Code: Select all

// while there are elements in the response object, read each individual element and store it in $my_array
$my_array[$count]= array("rating" => $val->productDetails->propertyDetails->starRating, "price" => parse($val->adultPrice->totalPrice->sourceCurrencyPrice), "image" => $val->productDetails->propertyDetails->mainImageURL, "hotel" => $val->productDetails->propertyDetails->fullHotelName, "depDate" => $val->productDetails->departureDate, "retDate" => $val->productDetails->returnDate, "duration" => $val->productDetails->tripDuration, "code" => $val->productDetails->packageCode, "operator" => $val->productDetails->tourOperator, "meal" => $val->productDetails->mealPlan, "room" => $val->productDetails->roomOccupancy, "taxes" => $val->adultPrice->arrayOfTaxes->TaxPrice->sourceCurrencyPrice, "currency" => $val->adultPrice->totalPrice->sourceCurrency, "index" => $val->outputIndex);
2. Create a second array with sorting definition:

Code: Select all

$howToSort[$count] = array("rating" => 'desc', "price" => 'desc');
3. After loop is finished, call the function to multisort

Code: Select all

processArrays($my_array, $howToSort)

function processArrays($my_array, $howToSort)
{
        array_multisort($my_array, $howToSort);

        //display the sorted contents of $my_array
}
So instead of dealing with 14 arrays, I have 1 and I think there is some memory improvement because PHP doesn't have to allocate memory to 13 other objects (but I am not sure about this one because I don't know exactly how PHP works).

Thank you again for your comment, I just got lucky in finding this solution through Google :)

Thank you,
Victor.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

If you look at the PHP manual, there is a user comment that discusses the same method you employ. I like that method better than the one I supplied, but it sounded like you needed a solution that the function posted provided.

Regardless, I am glad you got it all sorted out.
Post Reply