2

I have following array

Array
(
[0] => Array
    (
        [label] => Germany
        [conversions] => 1
    )

[1] => Array
    (
        [label] => United States
        [conversions] => 8
    )

[2] => Array
    (
        [label] => France
        [conversions] => 1
    )

[3] => Array
    (
        [label] => China
        [conversions] => 1
    )

[4] => Array
    (
        [label] => Philippines
        [conversions] => 1
    )

[5] => Array
    (
        [label] => Turkey
        [conversions] => 1
    )

)

I want to order following array, first by conversions (desc), then by label (asc)

output will have following sequence:

United States
China
France
Germany
Philippines
Turkey
1

6 Answers 6

4

If using >= PHP 5.3...

usort($arr, function($a, $b) {

   $diff = $b['conversions'] - $a['conversions'];

   if ( ! $diff) {
      return strcmp($a['label'], $b['label']);
   } 

   return $diff; 

});

It is relatively simple to make it work with < PHP 5.3.

Sign up to request clarification or add additional context in comments.

6 Comments

Typo in the second conversions index.
note that functions can only be defined this way in PHP 5.3 and above. If you're using an older version of PHP, you'll need to define your function in the traditional way, and the second param of usort() would be the function name. (you may want to do this anyway, if you plan to use the same sorting function in more than one place)
@alex: Edited: The code did not work at all even in PHP 5.3 (it's not complete so gives syntax errors) and well, the sort order was wrong.
@hakre: Thanks, I didn't test it. I would have if the OP gave the array in an easy copy + paste format. :)
@alex: little hint: visit my profile page and look into the grey box on the right. there is one link. I know perfectly how you feel ;)
|
1

You need to use PHP's usort() function. This allows you to write a function which determines the sort order, so you can sort things into any order you like.

The function will be called repeatedly by the usort() algorithm, and will give you two parameters, being the two elements of the array that it wants to sort at any given moment. Your function should return -1 if the first of those two elements is bigger, +1 if it the second is bigger, and zero if they are to be considered the same for the purposes of the sort.

See the PHP manual page for more info and examples: http://php.net/manual/en/function.usort.php

Comments

1

I preferred array_multisort PHP Manual in my answer below as you can specify the sort order with parameters.

Next to flexibility it should be faster than using usort which has the problem that it's not really parametrized for the sort order, so not re-inventing the wheel as well.

For more comfort, wrap it up into a function to specify the keys as strings (Demo):

$sorted = $multisortByKey($array, 'conversions', SORT_DESC, 'label', SORT_ASC);

as in:

$array = array(
  0 => array(
    'label' => 'Germany',
    'conversions' => 1,
  ),
  1 => array(
    'label' => 'United States',
    'conversions' => 8,
  ),
  2 => array(
    'label' => 'France',
    'conversions' => 1,
  ),
  3 => array(
    'label' => 'China',
    'conversions' => 1,
  ),
  4 => array(
    'label' => 'Philippines',
    'conversions' => 1,
  ),
  5 => array(
    'label' => 'Turkey',
    'conversions' => 1,
  ),
);

$multisortByKey = function(array $a) {
    $args = func_get_args();
    $a = array_shift($args);
    $extract = function($k) use($a) {return array_map(function($v) use($k) { return $v[$k]; }, $a); };
    # NOTE: The following check/for-loop is not entirely correct 
    # as multiple sort parameters per entry are allowed. I leave this
    # for practice.
    $c = count($args);
    if(!$c%2) throw new InvalidArgumentException('Parameter count mismatch');
    for($i=0;$i<$c;$i+=2)
        $args[$i] = $extract($args[$i]);
    $args[] = &$a;
    call_user_func_array('array_multisort', $args);
    return $a;
};

$sorted = $multisortByKey($array, 'conversions', SORT_DESC, 'label', SORT_ASC);

var_dump($sorted);

Comments

0

try this

$myArray="your array";

<?php

foreach($myArray as $c=>$key) {
    $sort_conv[$c] = $key['conversions'];
    $sort_lable[$c] = $key['label'];
   }

array_multisort($sort_conv, SORT_ASC, $sort_lable, SORT_STRING, $myArray);
print_r($myArray);
?>

1 Comment

Actually this isn't correct. Indeed your proposed code sorts at first by conversions in ascending order, but as a second sorting criteria OP didn't ask for an alphabetical sorting, but rather using a specific sorting country criterion...
0

You can use usort to provide your own sorting function

usort($a, function($x, $y) {
  return $y["conversions"] < $x["conversions"] ? 1 :
    ($x["conversions"] < $y["conversions"] ? -1 :
      strcmp($x["label"], $y["label"]))
    );
});

Comments

0

Try the following: (didn't test it, source: PHP Example #3)

foreach ($data as $key => $row) {
    $label[$key]   = $row['label'];
    $conversion[$key] = $row['conversion'];
}

array_multisort($conversion, SORT_DESC, $label, SORT_ASC, $data);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.