0

Suppose I have an array that I want to sort, and the order is not something computable, but rather, given by another array which lists the keys in the desired order:

$ordering_array = [
    'c',
    'a',
    'k',
    'e',
];

As an added complication, not all of these keys might be present in my array to sort:

$given_array = [
    'a' => 'value',
    'c' => 'value',
    'e' => 'value',
];

What is the cleanest / quickest way to achieve this?

My method is:

$new_array = array_fill_keys($ordering_array, NULL);

foreach ($given_array as $key => $value) {
  $new_array[$key] = $value;
}

$new_array = array_filter($new_array);

Is there a better way?

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
joachim
  • 28,554
  • 13
  • 41
  • 44

6 Answers6

2

You can replace the foreach with array_replace()

$new_array = array_fill_keys($ordering_array, NULL);
$new_array = array_replace($new_array, $given_array);
$new_array = array_filter($new_array);
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
1

you can try this

$filteredKeys = array_intersect_key(array_flip($ordering_array), $given_array);
$outputArray = array_merge($filteredKeys, $given_array);
rkj
  • 8,067
  • 2
  • 27
  • 33
1

Use array_merge() or array_replace at the place of foreach, both worked

Try this:

$ordering_array = ['c', 'a', 'k', 'e'];
$given_array = ['a' => 'value', 'c' => 'value', 'e' => 'value'];

$new_array = array_fill_keys($ordering_array, NULL);

$new_array = array_merge($new_array, $given_array);
                       OR
$new_array = array_replace($new_array, $given_array);

$new_array = array_filter($new_array);
Jagjeet Singh
  • 1,564
  • 1
  • 10
  • 23
1

This is a oneliner that solves it:

$ordering_array = ['c', 'a', 'k', 'e'];
$given_array = ['a' => 'value', 'c' => 'value', 'e' => 'value'];
$outputArray = array_merge(array_intersect_key(array_flip($ordering_array), $given_array), $given_array);
print_r($outputArray);

@rkj was close, but this is how it's done

Test here: http://sandbox.onlinephpfunctions.com/code/95b30f6e402b1afdb18867471888ff8ba38867de

NoOorZ24
  • 2,914
  • 1
  • 14
  • 33
0

try using uksort,

demo

<?php 
    $ordering_array  = [
        'c',
        'a',
        'k',
        'e',
    ];
    $given_array  = [
        'a' => 'value-a',
        'c' => 'value-c',
        'e' => 'value-e',
    ];

    uksort($given_array , function ($a, $b) use ($ordering_array) {

        $pos_a = array_search($a,$ordering_array);
        $pos_b = array_search($b,$ordering_array);
        return $pos_a - $pos_b;
    });

    var_dump($given_array );
Jayakrishnan
  • 1,295
  • 2
  • 13
  • 27
  • 1
    If you flip the ordering_array you can throw away the array_search lines, and change the return to: `return $ordering_array[$a] - $ordering_array[$b];` – Progrock Jun 22 '18 at 08:01
0

Simple and explicit:

<?php    
$ordering_array = [
    'c',
    'a',
    'k',
    'e',
];

$given_array = [
    'a' => 'valuea',
    'c' => 'valuec',
    'e' => 'valuee',
];

foreach($ordering_array as $K)
    if(array_key_exists($K, $given_array))
        $ordered[$K] = $given_array[$K];

var_export($ordered);

Output:

array (
  'c' => 'valuec',
  'a' => 'valuea',
  'e' => 'valuee',
)

You might be able to shave off a byte or two with isset($given_array[$K]) if the data allows.

Progrock
  • 7,373
  • 1
  • 19
  • 25