0

I have an array:

$arr = ['item_one', 'item_two'];

By default those keys are 0 and 1 and if i dump that array it looks like this:

array(2) { [0]=> string(8) "item_one" [1]=> string(8) "item_two" }

Instead of first $arr default key 1 i want to set it to 25 and then identify the fact that it was set instead of automatically generated:

$arr = ['item_one', '25' => 'item_two'];

I tried this:

foreach($arr as $k => $v){
    if(is_int($k)){
        echo '[' . $k . '] is not a custom key!'.
    }
}

But the output is:

[0] is not a custom key!
[25] is not a custom key!

Because obviously both keys are (int).

How do i get key 25 to not output that message?

emma
  • 761
  • 5
  • 20

2 Answers2

1

Can you try my code:

$arr = ['item_one', '25' => 'item_two'];
$i = 0;
foreach($arr as $k => $v){
    if($i != $k){
        echo '[' . $k . '] is a custom key!';
    }
    $i++;
}
Ryan Nghiem
  • 2,417
  • 2
  • 18
  • 28
  • duck typing is going to mess with you. Use `!==` – Tim Morton Jan 08 '20 at 01:35
  • 1
    @TimMorton Use `! = `Can exclude the key `0` and correctly find out that `25` is a custom key in this case, Not all cases should use `! ==`. – Calos Jan 08 '20 at 01:40
  • 1
    @CalosKao um, this proves that 1 != 25. That doesn’t prove it’s a string (or a so called custom key). – Tim Morton Jan 08 '20 at 01:58
  • @TimMorton I agree that this snippet cannot prove that the custom key is a string, and that this snippet will not work if the array length exceeds 26. – Calos Jan 08 '20 at 02:06
  • ...and what if `$arr = ['item1','25'=>'item2','2'=>'item3'];`? – Tim Morton Jan 08 '20 at 03:09
  • This code will not work if i want to set a custom key to `0` or as @TimMorton said in a descending order. – emma Jan 08 '20 at 09:24
1

Aside from some trickery with objects that may or may not work, the only solution I can see is to make duck typing work for you instead of against you:

Prepend a space or 0 in front of the number. It will then be a string in the key " 25" or "025", but will convert to an integer if you use it as a number or cast it as an integer elsewhere.

php > $arr = ['item_one', '025' => 'item_two'];
php > foreach($arr as $k => $v) {
php { if(is_int($k)) {
php { echo '['.$k.'] is not a custom key!';
php { }
php { }
[0] is not a custom key!
php >

Simply comparing the key to the position within the element is not reliable:

php > $arr = ['item_one','25'=>'item_two','2'=>'item_three'];
php > $i=0;
php > foreach($arr as $k=>$v) {
php { if($i != $k) {
php { echo '['.$k.'] is a custom key';
php { }
php { $i++;
php { }
[25] is a custom key
php >

(note:  missed $arr['2'])

According to the manual:

The key can either be an integer or a string. The value can be of any type.

Additionally the following key casts will occur:

  • Strings containing valid decimal integers, unless the number is preceded by a + sign, will be cast to the integer 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.
  • Floats are also cast to integers, which means that the fractional part will be truncated. E.g. the key 8.7 will actually be stored under 8.
  • Bools are cast to integers, too, i.e. the key true will actually be stored under 1 and the key false under 0. Null will be cast to the empty string, i.e. the key null will actually be stored under "".
  • Arrays and objects can not be used as keys. Doing so will result in a warning: Illegal offset type.

If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.

Community
  • 1
  • 1
Tim Morton
  • 2,614
  • 1
  • 15
  • 23
  • Hey @TimMorton, so basically there's no other way to set a key as a string when using digits in php except for duck typing? :( – emma Jan 08 '20 at 09:49
  • 1
    @emma I added the manual reference to the answer. Duck typing is going to work hard to prevent what you're wanting to do, unfortunately. The only way I know to force a number string to remain a string is to prepend a space, zero or plus sign. – Tim Morton Jan 08 '20 at 14:55
  • this is so sad ... i think i;m going to use some character that will be removed inside that foreach. Wouldn't it make more sense to be a string if encapsulated by "" ? – emma Jan 08 '20 at 15:27