views:

103

answers:

3

I have an array composed of arrays. I want to sort the parent array by a property of the child arrays. Here's an example

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(6) "105945"
    [1]=>
    string(10) "First name"
    [2]=>
    float(0.080878465391)
  }
  [1]=>
  array(3) {
    [0]=>
    string(6) "109145"
    [1]=>
    string(11) "Second name"
    [2]=>
    float(0.0504154818384)
}

I would like to sort the parent array by [2] ascending in the child arrays, so in this case the result would be the child arrays reversed (.05, 08). Is this possible using any of the numerous PHP sort functions?

+5  A: 

You can make use of usort function as:

$arr = array(
                array("105945","First name",0.080878465391),
                array("109145","Second name",0.0504154818384)
            );

function cmp($a, $b) {
        if ($a[2] == $b[2]) {
                return 0;
        }
        return ($a[2] < $b[2]) ? -1 : 1;
}

usort($arr,"cmp");
codaddict
Example #2 on that page is very similar to what you're trying to do, take a look at that.
Chad Birch
Have updated my answer with exactly what you want.
codaddict
Wow, incredibly helpful answer. Thank you.
Evan
A: 

Hi, see this page for example

http://php.net/manual/en/function.sort.php

or example

      <?php 
function multisort($array, $sort_by) {
    foreach ($array as $key => $value) {
        $evalstring = '';
        foreach ($sort_by as $sort_field) {
            $tmp[$sort_field][$key] = $value[$sort_field];
            $evalstring .= '$tmp[\'' . $sort_field . '\'], ';
        }
    }
    $evalstring .= '$array';
    $evalstring = 'array_multisort(' . $evalstring . ');';
    eval($evalstring);

    return $array;
} 

$test = array(
    array( 'a' => '1', 'b' => '3'),
    array( 'a' => '2', 'b' => '1'),
    array( 'a' => '1', 'b' => '1'));

echo 'Unsorted: ';
print_r($test);

$result = multisort( $test , array('a','b') );

echo 'Sorted: ';
print_r($result);
?>

Result:

Unsorted: Array
(
    [0] => Array
        (
            [a] => 1
            [b] => 3
        )

    [1] => Array
        (
            [a] => 2
            [b] => 1
        )

    [2] => Array
        (
            [a] => 1
            [b] => 1
        )

)
Sorted: Array
(
    [0] => Array
        (
            [a] => 1
            [b] => 1
        )

    [1] => Array
        (
            [a] => 1
            [b] => 3
        )

    [2] => Array
        (
            [a] => 2
            [b] => 1
        )

)
Karthik
This is some very scary code - I highly suggest that you don't use it. Use `usort()` as recommended.
Chad Birch
hey usort() function is already provided. So only i provide the alternative solution that i provide the example from manual.
Karthik
A: 

I think the following will help u

<?php
$testAry = array(
  array('a' => 1, 'b' => 2, 'c' => 3),
  array('a' => 2, 'b' => 1, 'c' => 3),
  array('a' => 3, 'b' => 2, 'c' => 1),
  array('a' => 1, 'b' => 3, 'c' => 2),
  array('a' => 2, 'b' => 3, 'c' => 1),
  array('a' => 3, 'b' => 1, 'c' => 2)
);

Utility::orderBy($testAry, 'a ASC, b DESC');

//Result:
$testAry = array(
  array('a' => 1, 'b' => 3, 'c' => 2),
  array('a' => 1, 'b' => 2, 'c' => 3),
  array('a' => 2, 'b' => 3, 'c' => 1),
  array('a' => 2, 'b' => 1, 'c' => 3),
  array('a' => 3, 'b' => 2, 'c' => 1),
  array('a' => 3, 'b' => 1, 'c' => 2)
);
?>

To sort an array of objects you would do something like:
Utility::orderBy($objectAry, 'getCreationDate() DESC, getSubOrder() ASC');

This would sort an array of objects that have methods getCreationDate() and getSubOrder().

Here is the function:

<?php
class Utility {
    /*
    * @param array $ary the array we want to sort
    * @param string $clause a string specifying how to sort the array similar to SQL ORDER BY clause
    * @param bool $ascending that default sorts fall back to when no direction is specified
    * @return null
    */
    public static function orderBy(&$ary, $clause, $ascending = true) {
        $clause = str_ireplace('order by', '', $clause);
        $clause = preg_replace('/\s+/', ' ', $clause);
        $keys = explode(',', $clause);
        $dirMap = array('desc' => 1, 'asc' => -1);
        $def = $ascending ? -1 : 1;

        $keyAry = array();
        $dirAry = array();
        foreach($keys as $key) {
            $key = explode(' ', trim($key));
            $keyAry[] = trim($key[0]);
            if(isset($key[1])) {
                $dir = strtolower(trim($key[1]));
                $dirAry[] = $dirMap[$dir] ? $dirMap[$dir] : $def;
            } else {
                $dirAry[] = $def;
            }
        }

        $fnBody = '';
        for($i = count($keyAry) - 1; $i >= 0; $i--) {
            $k = $keyAry[$i];
            $t = $dirAry[$i];
            $f = -1 * $t;
            $aStr = '$a[\''.$k.'\']';
            $bStr = '$b[\''.$k.'\']';
            if(strpos($k, '(') !== false) {
                $aStr = '$a->'.$k;
                $bStr = '$b->'.$k;
            }

            if($fnBody == '') {
                $fnBody .= "if({$aStr} == {$bStr}) { return 0; }\n";
                $fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";               
            } else {
                $fnBody = "if({$aStr} == {$bStr}) {\n" . $fnBody;
                $fnBody .= "}\n";
                $fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";
            }
        }

        if($fnBody) {
            $sortFn = create_function('$a,$b', $fnBody);
            usort($ary, $sortFn);       
        }
    }
}
?>
kvijayhari
Dear god. Is this some sort of joke?
Chad Birch
The above function is used to sort based on more than one group of values and also on both ascending and descending order.. Notice that the first values are every subarray are sorted ascending and the next values are sorted in the descending order...
kvijayhari