array_walk_recursive - modify both keys and values

This my recursive function that can change not only the values of the array as array_walk_recursive() but also the keys of the given array. It also keeps the order of the array.

/**
 * Change values and keys in the given array recursively keeping the array order.
 *
 * @param array    $_array    The original array.
 * @param callable $_callback The callback function takes 2 parameters (key, value)
 *                            and returns an array [newKey, newValue] or null if nothing has been changed.
 *
 * @return void
 */
function modifyArrayRecursive(array &$_array, callable $_callback): void
{
    $keys = \array_keys($_array);
    foreach ($keys as $keyIndex => $key) {
        $value = &$_array[$key];
        if (\is_array($value)) {
            modifyArrayRecursive($value, $_callback);
            continue;
        }

        $newKey = $key;
        $newValue = $value;
        $newPair = $_callback ($key, $value);
        if ($newPair !== null) {
            [$newKey, $newValue] = $newPair;
        }

        $keys[$keyIndex] = $newKey;
        $_array[$key] = $newValue;
    }

    $_array = \array_combine($keys, $_array);
}

/**
 * Usage example
 */
modifyArrayRecursive($keyboardArr, function ($key, $value) {
    if ($value === 'some value') {
        return ['new_key_for_this_value', $value];
    }

    return null;
});

array_walk_recursive does ONLY apply the user function on the VALUES of an array, not on indexes (I think it has something to with the fact, that the indexes of an array have to be unique, so you cannot manipulate them). Best thing would be to write a recursive function on yourself. The following should work:

function utf8enc($array) {
    if (!is_array($array)) return;
    $helper = array();
    foreach ($array as $key => $value) $helper[utf8_encode($key)] = is_array($value) ? utf8enc($value) : utf8_encode($value);
    return $helper;
}

$enc_array = utf8enc($your_array);

Tags:

Php