joachim
joachim

Reputation: 30821

what's the best way to order an array using another in PHP?

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?

Upvotes: 0

Views: 117

Answers (6)

Progrock
Progrock

Reputation: 7485

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.

Upvotes: 0

Jayakrishnan
Jayakrishnan

Reputation: 1335

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

Upvotes: 0

rkj
rkj

Reputation: 8297

you can try this

$filteredKeys = array_intersect_key(array_flip($ordering_array), $given_array);
$outputArray = array_merge($filteredKeys, $given_array);

Upvotes: 1

Jagjeet Singh
Jagjeet Singh

Reputation: 1572

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

Upvotes: 1

NoOorZ24
NoOorZ24

Reputation: 3257

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

Upvotes: 1

Nigel Ren
Nigel Ren

Reputation: 57131

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

Upvotes: 2

Related Questions