Пересечение с помощью массивов с числовыми строковыми клавишами

Чтобы понять, почему я спрашиваю об этом, прочитайте это и комментарии к нему. Рассмотрим следующий код:

$obj = new stdClass; $obj->{10} = 'Thing'; $objArray = (array) $obj; var_dump($objArray); 

Производит:

 array(1) { ["10"]=> string(5) "Thing" } 

Теперь я не могу получить доступ к этому через $objArray['10'] потому что PHP преобразует числовые строки в целые ключи. В руководстве явно указывается, что «целочисленные свойства недоступны» при бросании массива в объект. Или они?

Чтобы доказать неправильные документы, я создал класс:

 class strKey implements ArrayAccess { private $arr; public function __construct(&$array) { $this->arr = &$array; } public function offsetExists($offset) { foreach ($this->arr as $key => $value) { if ($key == $offset) { return true; } } return false; } public function offsetGet($offset) { foreach ($this->arr as $key => $value) { if ($key == $offset) { return $value; } } return null; } public function offsetSet($offset, $value) { foreach($this->arr as $key => &$thevalue) { if ($key == $offset) { $thevalue = $value; return; } } // if $offset is *not* present... if ($offset === null) { $this->arr[] = $value; } else { // this won't work with string keys $this->arr[$offset] = $value; } } // can't implement this public function offsetUnset($offset) { foreach ($this->arr as $key => &$value) { if ($key == $offset) { //$value = null; } } } } 

Теперь я могу сделать (demo) :

 $b = new strKey($objArray); echo $b['10']; // Thing $b['10'] = 'Something else'; // because the classes works with a reference to the original array, // this will give us a modified array: var_dump($objArray); 

Последний фрагмент головоломки: как мне удалить элемент, чей ключ является числовой строкой? Я попытался использовать ArrayIterator , key() , next() и т. Д., Но это не сработает. Я не могу найти способ устранить это.

Любое решение должно работать с исходным массивом, а не создавать копию и заменять оригинал.

Вы можете попытаться удалить его с помощью array_splice() , если знаете его смещение ( foreach (...) { $offset++; ... } ), но хранение данных в таких массивах, как это, действительно не очень хорошая идея. Вы должны преобразовать эти объекты в массив с foreach:

 foreach ( $obj as $key => $value ) $array[$key] = $value; 

Следуя совету pozs, вот результат offsetUnset() . Я также добавил новый offsetSet() который поддерживает добавление цифровых клавиш.

 public function offsetUnset($offset) { $off = 0; foreach ($this->arr as $key => $value) { if ($key === $offset) { array_splice($this->arr, $off, 1); return; } $off++; } } public function offsetSet($offset, $value) { foreach($this->arr as $key => &$thevalue) { if ($key === $offset) { $thevalue = $value; return; } } // if $offset is *not* present... if ($offset === null) { $this->arr[] = $value; } // it's a numeric string key, now we have to hack it else if (strval(intval($offset)) === $offset) { // create new array via loophole: $tempObj = new stdClass; $tempObj->{$offset} = $value; // append to old array (+= doesn't create copies) $this->arr += (array) $tempObj; unset($tempObj); } // we are dealing with a normal key else { $this->arr[$offset] = $value; } } с public function offsetUnset($offset) { $off = 0; foreach ($this->arr as $key => $value) { if ($key === $offset) { array_splice($this->arr, $off, 1); return; } $off++; } } public function offsetSet($offset, $value) { foreach($this->arr as $key => &$thevalue) { if ($key === $offset) { $thevalue = $value; return; } } // if $offset is *not* present... if ($offset === null) { $this->arr[] = $value; } // it's a numeric string key, now we have to hack it else if (strval(intval($offset)) === $offset) { // create new array via loophole: $tempObj = new stdClass; $tempObj->{$offset} = $value; // append to old array (+= doesn't create copies) $this->arr += (array) $tempObj; unset($tempObj); } // we are dealing with a normal key else { $this->arr[$offset] = $value; } } 

Я официально победил PHP. Ура!