Sort Multi-dimensional array by decimal values
Asked Answered
B

6

8

What I'm trying to do is sort a multi-dimensional array that contains decimal values. From what I've tested, floats are having trouble being ordered properly.

Array
(
    [0] => Array
        (
            [company] => Ebay
            [weight] => 4.6
        )

    [1] => Array
        (
            [company] => Ebay
            [weight] => 1.7
        )

    [2] => Array
        (
            [company] => Ebay
            [weight] => 3.7
        )
)


usort($array, 'order_by_weight');

// Sorts DESC highest first
function order_by_weight($a, $b) {
    return $b['weight'] - $a['weight'];
}

What is the best way to sort these numbers in descending?

Beitris answered 11/4, 2013 at 5:6 Comment(3)
"floats have trouble being ordered properly" --- no they aren't, you've confused something.Daffodil
I've taken your code and it just works: ideone.com/cqW85m Have you even tried to run it?Daffodil
done, there is an answer (took your code and slightly changed it)Daffodil
D
21
$arr = array(
    array('company' => 'A', 'weight' => 4.6),
    array('company' => 'B', 'weight' => 1.7),
    array('company' => 'C', 'weight' => 3.7),
);

usort($arr, 'order_by_weight');

function order_by_weight($a, $b) {
    return $b['weight'] > $a['weight'] ? 1 : -1;
}

var_dump($arr);

PS: it's not a rocket science - this exact "trick" is used as the first example at http://php.net/usort

Daffodil answered 11/4, 2013 at 5:20 Comment(4)
I like it, much shorter than array_multisort and simple to read/use!Decane
@Benz: it could be even shorter if we used anonymous functionsDaffodil
Totally true, but we don't know the TS PHP version, I'm not for sure, but I thought that the minimal PHP version for anonymous functions is PHP 5.4.Decane
@Benz: it's 5.3, which is quite popular these daysDaffodil
K
3

You can do this with anonymous function in just one line

$arr = array(
    array('company' => 'A', 'weight' => 4.6),
    array('company' => 'B', 'weight' => 1.7),
    array('company' => 'C', 'weight' => 3.7),
);
usort($arr, function($a, $b) { return $b['weight'] > $a['weight'] ;});

print_r($arr);

Hope this helps :)

Kisumu answered 11/4, 2013 at 5:34 Comment(0)
D
1

You can sort the array using array_multisort, altough, this is often used to sort on multiple array values instead of one.

echo "<pre>";

 $a = array(
     array('company' => 'ebay', 'weight' => 4.6), 
     array('company' => 'ebay', 'weight' => 1.7),
     array('company' => 'ebay', 'weight' => 3.7),
     array('company' => 'ebay', 'weight' => 2.7),
     array('company' => 'ebay', 'weight' => 9.7),
     array('company' => 'ebay', 'weight' => 0.7),
 );

 $company = array();
 $weight = array();

 foreach($a as $key=>$val) {
     array_push($company, $val['company']);
     array_push($weight, $val['weight']);
 }

 array_multisort($weight, SORT_ASC, $a);

 print_r($a);
Decane answered 11/4, 2013 at 5:20 Comment(0)
I
0

As sorting algo here is good example for sort multi dimension array without using any more inbuilt php function

$multiarr = array('0'=>array(
        "hashtag" => "a7e87329b5eab8578f4f1098a152d6f4",
        "title" => "Flower",
        "order" => 3),

'1' => array(
        'hashtag' => "b24ce0cd392a5b0b8dedc66c25213594",
        "title" => "Free",
        "order" => 2),
'2' => array('hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
        'title' => 'Ready',
        'order' => 1
    ));

sorting function :

function multisort(&$array, $key) {
    $valsort = array();
    $ret = array();
    reset($array);
    foreach ($array as $ii => $va) {
        $valsort[$ii] = $va[$key];
    }
    asort($valsort);
    foreach ($valsort as $ii => $va) {
        $ret[$ii] = $array[$ii];
    }
    $array = $ret;
}

multisort($multiarr, "order");

: output :

Array
 (
[2] => Array
    (
        [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
        [title] => Ready
        [order] => 1
    )

[1] => Array
    (
        [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
        [title] => Free
        [order] => 2
    )

[0] => Array
    (
        [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
        [title] => Flower
        [order] => 3
    )

)
Iffy answered 11/4, 2013 at 5:38 Comment(0)
F
0

In case someone wants a more concise code, especially to handle equals condition you will add if condition before @zerkms's solution

using ceil will round fractions up and will sort the decimal numbers correctly

usort($data, function($a, $b) 
      {
        return ceil($a[$_GET['sortby']] - $b[$_GET['sortby']]); 
      });
Fowle answered 13/1, 2021 at 9:0 Comment(1)
There is no reason to call ceil() or use subtraction from PHP7 and higher. The spaceship operator (three-way comparison operator) should be used every time -- it will even correctly compare numeric strings as numbers.Wrestle
W
0

None of the earlier posted answers are demonstrating the most modern syntaxes for sorting by a column value.

If using usort(), use the three-way comparison operator ("spaceship operator ") from PHP7 and if you are on PHP7.4 or higher enjoy the brevity of "arrow function" syntax. For descending directional sorting write $b on the left of the operator and $a on the right. (Demo)

usort($arr, fn($a, $b) => $b['weight'] <=> $a['weight']);

array_multisort() can also be used, but it requires an additional loop to isolate a column of data. (Demo)

array_multisort(array_column($arr, 'weight'), SORT_DESC, $arr);
Wrestle answered 4/2, 2023 at 3:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.