5

I can sort a multidimensional array but without keeping the numerical index association.

How can I keep the numerical index association?

CODE:

$waiters[76] = array('weight' => 67, 'specialties' => 1);
$waiters[14] = array('weight' => 41, 'specialties' => 2);
$waiters[58] = array('weight' => 85, 'specialties' => 3);
$waiters[89] = array('weight' => 98, 'specialties' => 4);
$waiters[68] = array('weight' => 86, 'specialties' => 5);
$waiters[31] = array('weight' => 13, 'specialties' => 6);
print_r($waiters);
// Obtain a list of waiters
foreach ($waiters as $id => $waiter) {
    $weight[$id]        = $waiter['weight'];
    $specialties[$id]   = $waiter['specialties'];

}

// Sort the data with weight descending, specialties ascending
// Add $data as the last parameter, to sort by the common key
array_multisort(
    $weight, SORT_DESC, SORT_NUMERIC, 
    $specialties, SORT_ASC, SORT_NUMERIC, 
    $waiters
);
print_r($waiters);

OUTPUT:

Array
(
    [0] => Array
        (
            [weight] => 98
            [specialties] => 4
        )

    [1] => Array
        (
            [weight] => 86
            [specialties] => 5
        )

    [2] => Array
        (
            [weight] => 85
            [specialties] => 3
        )

    [3] => Array
        (
            [weight] => 67
            [specialties] => 1
        )

    [4] => Array
        (
            [weight] => 41
            [specialties] => 2
        )

    [5] => Array
        (
            [weight] => 13
            [specialties] => 6
        )

)

DESIRED OUTPUT:

Array
(
    [89] => Array
        (
            [weight] => 98
            [specialties] => 4
        )

    [68] => Array
        (
            [weight] => 86
            [specialties] => 5
        )

    [58] => Array
        (
            [weight] => 85
            [specialties] => 3
        )

    [76] => Array
        (
            [weight] => 67
            [specialties] => 1
        )

    [14] => Array
        (
            [weight] => 41
            [specialties] => 2
        )

    [31] => Array
        (
            [weight] => 13
            [specialties] => 6
        )

)
itsazzad
  • 5,660
  • 6
  • 58
  • 76
  • @Naruto The possible duplication is using `usort` but I am using `array_multisort` – itsazzad May 19 '14 at 15:15
  • 3
    Create your own user function instead, which would solve your problem and make the question the same. – vogomatix May 19 '14 at 15:33
  • @vogomatix Please check the question edit. The old question was making it duplicate. Now it should not be duplicate. – itsazzad May 19 '14 at 15:39
  • 1
    You are missing the point - the answer to the problem is still to create your own comparison function and use uasort as the linked question suggests, Just because a anrray_multisort method exists doesn't necessarily mean you *have* to use it. – vogomatix May 19 '14 at 15:43
  • @SazzadHossainKhan If you had read the documentation of array_multisort you know you can't keep the index.. It clearly says, and I quote: 'Associative (string) keys will be maintained, but numeric keys will be re-indexed.' – Naruto May 20 '14 at 07:41
  • Hi guys. I've just experienced this issue and needed a simple solution (without changing array_multisort to another function). I came up with a simple solution: Add a prefix to your array keys, then multisort, then remove the array key prefix. The prefix will ensure the array is associative! I made 2 helper functions to add and remove the prefix, so it's pretty tidy – Elliot Condon Sep 15 '16 at 05:26
  • @ElliotCondon seems to be a costlier workaround. Will you be able to post the solution as an answer? – itsazzad Sep 18 '16 at 01:14

2 Answers2

9
$keys = array_keys($waiters);
array_multisort(
    $weight, SORT_DESC, SORT_NUMERIC,
    $specialties, SORT_ASC, SORT_NUMERIC,
    $waiters, $keys
);
$waiters = array_combine($keys, $waiters);

or use uasort

uasort(
    $data,
    function ($some_data, $another_data) {

        $result = 0;

        if ($some_data['weight'] > $another_data['weight']) {
            $result = -1;
        } elseif ($some_data['weight'] < $another_data['weight']) {
            $result = 1;
        } elseif ($some_data['specialties'] > $another_data['specialties']) {
            $result = 2;
        } elseif ($some_data['specialties'] < $another_data['specialties']) {
            $result = -2;
        }

        return $result;

    }
);

but the uasort performance is significantly worse than array_multisort

Artkom
  • 91
  • 1
  • 3
1

For Your Desired output use this code:

<?php
$waiters[76] = array('weight' => 67, 'specialties' => 1);
$waiters[14] = array('weight' => 41, 'specialties' => 2);
$waiters[58] = array('weight' => 85, 'specialties' => 3);
$waiters[89] = array('weight' => 98, 'specialties' => 4);
$waiters[68] = array('weight' => 86, 'specialties' => 5);
$waiters[31] = array('weight' => 13, 'specialties' => 6);

//ksort($waiters);
//$waiters = array_reverse($waiters, true);
print_r($waiters);
// Obtain a list of waiters
foreach($waiters as $id=>$w){
    $w[$id] = $w['weight'];
}
    foreach ($waiters as $ii => $va) {
        $sorter[$ii] = $va['weight'];

    }

    natcasesort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii] = $waiters[$ii];
    }

    echo "<pre>";
    $ret = array_reverse($ret, true);
    print_r($ret);

?>
dhruv jadia
  • 1,687
  • 2
  • 14
  • 28