Question

I have an array of associative arrays and the keys within each row are not in the order that I'd like them. How can I adjust all rows to have their associative keys in a pre-defined order?

My input array:

$array = [
    [
        'FirstName' => 'Robin',
        'Address' => 'Cave',
        'LastName' => 'Mactimmy',
        'Tel' => '9076',
        'Email' => 'i@o.com',
    ],
    [
        'Address' => 'uytr',
        'FirstName' => 'Bill',
        'Email' => 'j@k.com',
        'LastName' => 'Gates',
        'Tel' => '7654',
    ],
    [
        'LastName' => 'Mahoney',
        'Email' => 'y@i.ie',
        'FirstName' => 'Tom',
        'Tel' => '5689',
        'Address' => 'kklll',
    ]
];

My preferred order is FirstName, LastName, Address, Tel, Email and I have these values stored in an array.

I have tried ksort() and usort(), but with my code the array ordering does not seem to be updating.

My desired result:

[
    [
        'FirstName' => 'Robin',
        'LastName' => 'Mactimmy',
        'Address' => 'Cave',
        'Tel' => '9076',
        'Email' => 'i@o.com',
    ],
    [
        'FirstName' => 'Bill',
        'LastName' => 'Gates',
        'Address' => 'uytr',
        'Tel' => '7654',
        'Email' => 'j@k.com',
    ],
    [
        'FirstName' => 'Tom',
        'LastName' => 'Mahoney',
        'Address' => 'kklll',
        'Tel' => '5689',
        'Email' => 'y@i.ie',
    ]
]
Was it helpful?

Solution

Basic on your data:

$array = [
    0 => Array
        (
            'FirstName' => 'Robin',
            'Address' => 'Cave',
            'LastName' => 'Mactimmy',
            'Tel' => '9076',
            'Email' => 'i@o.com',
        ),

    1 => Array
        (
            'Address' => 'uytr',
            'FirstName' => 'Bill',
            'Email' => 'j@k.com',
            'LastName' => 'Gates',
            'Tel' => '7654',
        ),

    2 => Array
        (
            'LastName' => 'Mahoney',
            'Email' => 'y@i.ie',
            'FirstName' => 'Tom',
            'Tel' => '5689',
            'Address' => 'kklll',
        )
];

I think it is good solution:

<?php

$order = [ 'FirstName', 'LastName', 'Address', 'Tel', 'Email'];

$result = [];
foreach ($array as $sortable) {
    $result[] = array_merge(array_flip($order), $sortable);
}

print_r($result);

OTHER TIPS

You can use array_map in conjunction with array_merge. Something like this:

$result = array_map(
    function ($arr) use($sample) { return array_merge($sample, $arr); },
    $array
);

Here I assume that $array is object array and $sample is array with correct ordered keys.

Using a custom key sorter:

function cmp($a, $b) {
    // Custom key sort
}

uksort($array, "cmp");

or using recursive ksort:

ksortRecursive(&$array, $sort_flags = SORT_REGULAR) {
    if (!is_array($array)) return false;
    ksort($array, $sort_flags);
    foreach ($array as &$arr) {
        ksortRecursive($arr, $sort_flags);
    }
    return true;
}

Borrowed from: https://gist.github.com/cdzombak/601849

function cmp($a, $b)
{
    $order = array('FirstName' => 0, 'LastName' => 1, 'Address' => 2, 'Tel' => 3, 'Email' => 4);
    if ($a == $b || !isset($order[$a]) || !isset($order[$b])) {
        return 0;
    }
    return ($order[$a] < $order[$b]) ? -1 : 1;
}

uksort($a, "cmp");
function customArraySort($array, $exampleArray) {
  $returnArray = array();
    foreach($array as $arrIndex => $arrSubArr) {
      $returnArray[$arrIndex] = array();
        foreach($exampleArray as $exArIndex => $value)
          $returnArray[$arrIndex][$exArIndex] = $arrSubArr[$exArIndex];
    }
  return $returnArray;
}

array_walk() is a great tool for this task because it allows you to pass in an array to be used on each iteration.

Modify each row by reference and overwrite each row with the product of array_merge() which honors the desired keys while retaining the original values.

Code: (Demo)

array_walk(
    $array,
    fn(&$row, $index, $order) => $row = array_merge($order, $row),
    array_flip(['FirstName', 'LastName', 'Address', 'Tel', 'Email'])
);
var_export($array);

From PHP7.4, arrow function syntax eliminates the need to call use() to invite globally scoped data inside the custom function scope. array_map() returns the new array instead of modifying the original.

Code: (Demo)

$order = array_flip(['FirstName', 'LastName', 'Address', 'Tel', 'Email']);
var_export(
    array_map(fn($row) => array_merge($order, $row), $array)
);

For the record, because the arrays being used are associative, array_replace() can be used instead of array_merge() with the same effect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top