stwhite
stwhite

Reputation: 3275

Sort Multi-dimensional array by decimal values

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?

Upvotes: 8

Views: 9143

Answers (6)

mickmackusa
mickmackusa

Reputation: 47991

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);

Upvotes: 0

liyakat
liyakat

Reputation: 11853

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
    )

)

Upvotes: 0

Hassan Ibrahem
Hassan Ibrahem

Reputation: 51

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']]); 
      });

Upvotes: 0

Sabari
Sabari

Reputation: 6345

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 :)

Upvotes: 3

zerkms
zerkms

Reputation: 255015

$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

Upvotes: 21

Benz
Benz

Reputation: 2335

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);

Upvotes: 1

Related Questions