Custom sort an associative array by its keys using a lookup array
Asked Answered
H

3

2

I need to sort the following flat, associative array by its keys, but not naturally. I need to sort the keys by a predefined array of values.

$aShips = [
    '0_204' => 1,
    '0_205' => 2,
    '0_206' => 3,
    '0_207' => 4
];

My order array looks like this:

$order = ["0_206", "0_205", "0_204", "0_207"];

The desired result:

[
    '0_206' => 3,
    '0_205' => 2,
    '0_204' => 1,
    '0_207' => 4
]

I know how to write a custom sorting function, but I don't know how to integrate the order array.

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

uasort($aShips, "cmp");
Homorganic answered 29/11, 2016 at 14:41 Comment(0)
S
1

You don't need to leverage a sorting algorithm.

Simply flip $order to use its values as keys (maintaining their order), then merge the two arrays to replace the unwanted values of $order with the values from $aShip.

This assumes that $aShip includes all key values represented in $order, of course. If not, array_intersect_key() can be used to filter $order, but this is dwelling on a fringe case not included in the posted question.

Code: (Demo)

var_export(array_replace(array_flip($order), $aShips));

Output:

array (
  '0_206' => 3,
  '0_205' => 2,
  '0_204' => 1,
  '0_207' => 4,
)

This also works when you haven't listed every occurring key in $order -- the unlisted keys are "moved to the back". Proven by this Demo.


Using a custom sorting algorithm can be done and there will be a number of ways, but I'll only show one for comparison's sake.

Reverse your order array and use it as a lookup array while asking uksort() to sort in a descending fashion. If an encountered key is not found in the lookup assign it a value of -1 to ensure it moves to the back of the array.

Code: (Demo)

$lookup = array_flip(array_reverse($order));

uksort($aShips, function($a, $b) use ($lookup) {
    return ($lookup[$b] ?? -1) <=> ($lookup[$a] ?? -1);
});

var_export($aShips);

If you don't like reversing the lookup and sorting DESC, you can count the order array to determine a fallback value. This alternative script uses arrow function syntax for brevity and to gain direct access to the variables declared outside of the closure. (Demo)

$lookup = array_flip($order);
$default = count($order);

uksort($aShips, fn($a, $b) => ($lookup[$a] ?? $default) <=> ($lookup[$b] ?? $default));

var_export($aShips);
Shutz answered 13/12, 2019 at 20:50 Comment(0)
E
-1

According to the Official PHP Docs, you can use uasort() like this (just for demo):

<?php
// Comparison function
function cmp($a, $b) {
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

// Array to be sorted
$array = array('a' => 4, 'b' => 8, 'c' => -1, 'd' => -9, 'e' => 2, 'f' => 5, 'g' => 3, 'h' => -4);
print_r($array);

// Sort and print the resulting array
uasort($array, 'cmp');
print_r($array);
?>
Enlistment answered 29/11, 2016 at 14:43 Comment(1)
Hello Saumya Rastogi, i tried this but ist doesn't sort the array by my custom keys.Homorganic
F
-1

If you want to sort by keys. Use uksort. Try the code below.

<?php

$aShips = array('0_204' => 1, '0_205' => 2, '0_206' => 3, '0_207' => 4);

uksort($aShips, function($a, $b) {
    return $b > $a;
});
Foin answered 29/11, 2016 at 14:56 Comment(6)
thats the same array but reverse. I like to change the complete orderHomorganic
I'm not sure exactly what you mean by "I like to change complete order." There must be a criteria to sort it by. I'm not sure if you want to shuffle the order or remove the keys or values. It's confusing looking at your example. Can you please elaborate on the criteria to sort it by?Foin
i like it to order like: array("0_206", "0_205", "0_204", "0_207");Homorganic
or like array("0_207", "0_204", "0_206", "0_205"); etc (like my compar array "$order". Sorry for my bad englishHomorganic
If you want custom order, then you can iterate over the array and create a new array with the order you want.Foin
how...? split the array and then?Homorganic

© 2022 - 2024 — McMap. All rights reserved.