Philipp
Philipp

Reputation: 11391

Convert array keys from numeric string to integer

Due to serialization/deserialization of arrays I get incorrect data type of array keys in some cases.

$data = [
    0 => 'item 1',
    4 => 'item 2',
    7 => 'item 3',
];

$storage->set( 'demo', $data );

// ...and get it back later

$data = storage->get( 'demo' );
var_dump( $data );

/*
Result:

    array (size=3)
    "0" => string "item 1"
    "4" => string "item 2"
    "7" => string "item 3"

But I need (keys must be int):

    array (size=3)
    0 => string "item 1"
    4 => string "item 2"
    7 => string "item 3"
*/

Question: Is there an easy way to convert the keys back to integer?

I tried array_reverse( array_map( 'intval', array_reverse( $data ) ) ) but this loses items with different keys but identical values and most importantly it has problems with non-numeric keys.

Also array_values( $data ) did not solve the problem due to similar problems: It loses non-numeric keys and also keys are not sequential (it can be 0, 4, 7, but array_values() will assign keys 0, 1, 2)


Update - why this is important for my

We had problems with some website configuration because of this:

Upvotes: 2

Views: 13497

Answers (4)

Yevgeniy Afanasyev
Yevgeniy Afanasyev

Reputation: 41400

PHP documentation

Additionally the following key casts will occur:

Strings containing valid decimal ints, unless the number is preceded by a + sign, will be cast to the int type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer.

So you can use it, you don't need to check any conditions

Upvotes: 2

jkucharovic
jkucharovic

Reputation: 4244

Propably simplest solution:

$keys = array_keys($data);
$values = array_values($data);

$intKeys = array_map('intval', $keys);

$newData = array_combine($intKeys, $values);

Update:
With checking of key type:

$keys = array_keys($data);
if ($keys === array_filter($keys, 'is_numeric')) {

    $data = array_combine(
        array_map('intval', $keys),
        array_values($data)
    );    
}

Upvotes: 3

Philipp
Philipp

Reputation: 11391

Thanks to this great suggestion https://stackoverflow.com/a/45505894/313501 I came up with this code:

// Convert array keys to integer values, if array only contains numeric keys.
$is_numeric = array_reduce(
    array_keys( $data ),
    function( $res, $val ) { return $res && is_numeric( $val ); },
    true
);
if ( $is_numeric ) {
    $data = array_combine(
        array_map( 'intval', array_keys( $data ) ),
        array_values( $data )
    );
}

Upvotes: 0

Adder
Adder

Reputation: 5868

You can use is_numeric and intval to convert the keys:

$data2 = array();
foreach($data as $key=>$value) {
    $key2 = is_numeric($key) ? intval($key) : $key;
    $data2[$key2] = $value;
}

var_dump( $data2 );

Upvotes: 1

Related Questions