A Numeric String as Array Key in PHP

A numeric string as array key in PHP

No; no it's not:

From the manual:

A key may be either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08").

Addendum

Because of the comments below, I thought it would be fun to point out that the behaviour is similar but not identical to JavaScript object keys.

foo = { '10' : 'bar' };

foo['10']; // "bar"
foo[10]; // "bar"
foo[012]; // "bar"
foo['012']; // undefined!

How can I force PHP to use strings for array keys?

EDIT:

I assumed that if they are integers, I
can't reorder them without changing
the key (which is significant in this
example). However, if they were
strings, I can reorder them how they
like as the index shouldn't be
interpreted to have any special
meaning. Anyway, see my question
update for how I did it (I went down a
different route).

Actually they dont have to be in numeric order...

array(208=>'a', 0=> 'b', 99=>'c');

Is perfectly valid if youre assigning them manually. Though i agree the integer keys might be misinterpreted as having a sequential meaning by someone although you would think if they were in a non-numeric order it would be evident they werent. That said i think since you had the leeway to change the code as you updated that is the better approach.


Probably not the most efficient way but easy as pie:

$keys = array_keys($data);

$values = array_values($data);
$stringKeys = array_map('strval', $keys);

$data = array_combine($stringKeys, $values);

//sort your data

PHP array with numeric keys as string can't be used

So, I haven't seen any other answers touch upon this, but @xdazz came close.

Let's start our environment, $obj equals the object notation of a decoded string:

php > $obj = json_decode('{"1":1,"2":2}');

php > print_r($obj);
stdClass Object
(
[1] => 1
[2] => 2
)

php > var_dump( $obj );
object(stdClass)#1 (2) {
["1"]=>
int(1)
["2"]=>
int(2)
}

If you want to access the strings, we know the following will fail:

php > echo $obj->1;

Parse error: parse error, expecting `T_STRING' or `T_VARIABLE' or `'{'' or `'$'' in php shell code on line 1

Accessing the object variables

You can access it like so:

php > echo $obj->{1};
1

Which is the same as saying:

php > echo $obj->{'1'};
1

Accessing the array variables

The issue with arrays is that the following return blank, which is the issue with typecasting.

php > echo $obj[1];
php >

If you typecast it back, the object is once again accessible:

php > $obj = (object) $obj;
php > echo $obj->{1};
1

Here is a function which will automate the above for you:

function array_key($array, $key){
$obj = (object) $array;
return $obj->{$key};
}

Example usage:

php > $obj = (array) $obj;
php > echo array_key($obj, 1);
1

php > echo array_key($obj, 2);
2

Convert array keys from numeric string to integer

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

transform integer array keys to string array keys

This is not possible.

PHP will internally detect that it's a number (even in quotes) and convert it back. If you notice: the original array and the end one are identical. That's because PHP's automatically casting it for you.

The only way to prevent that is to not use numbers. You could prefix the numbers:

$a = [
"_0" => "a",
"_1" => "b",
]

But in general, you don't want to do that. And as you said, it's not even required by the code you thought it was.

And if you are wondering why it casts for you. I have one response. Because:

Because PHP

PHP: setting a number as key in associative array

Try

echo json_encode((object)$jsonobj);

target numeric keys only in array

Here's a complicated method using array_filter() to return the numeric keys then iterate over them.

// $input_array is your original array with numeric and string keys
// array_filter() returns an array of the numeric keys
// Use an anonymous function if logic beyond a simple built-in filtering function is needed
$numerickeys = array_filter(array_keys($input_array), function($k) {return is_int($k);});

// But in this simple case where the filter function is a plain
// built-in function requiring one argument, it can be passed as a string:
// Really, this is all that's needed:
$numerickeys = array_filter(array_keys($input_array), 'is_int');

foreach ($numerickeys as $key) {
// do something with $input_array[$key']
}

It's much easier though to just foreach over everything:

foreach ($input_array as $key => $val) {
if (is_int($key)) {
// do stuff
}
}

Edit Misread original post and thought I saw "numeric" rather than "integer" keys. Updated to use is_int() rather than is_numeric().



Related Topics



Leave a reply



Submit