Дублировать ключи в массиве

Каков наилучший способ предотвратить дублирование ключа при литье типов?

Пример :

//Credits @bwoebi $obj = (object)array(1,2,3); $obj->{1} = "Duplicate key 1"; $obj->{2} = "Duplicate key 2"; $obj->{3} = "Duplicate key 3"; $array = (array)$obj ; print_r($array); 

Вывод

 Array ( [0] => 1 [1] => 2 [2] => 3 [1] => Duplicate key 1 [2] => Duplicate key 2 [3] => Duplicate key 3 ) 

Теперь я знаю, что некоторые умные люди скажут его, потому что один key является string а другой int использует var_dump

 var_dump($array); 

Вывод

 array (size=6) 0 => int 1 1 => int 2 2 => int 3 '1' => string 'Duplicate key 1' (length=15) '2' => string 'Duplicate key 2' (length=15) '3' => string 'Duplicate key 3' (length=15) 

Но главная проблема заключается в том, что нет возможности даже получить ключ

 echo $array['1'] ,PHP_EOL; //Expected Duplicate key 1 echo $array[1] ,PHP_EOL; 

Вывод

 2 2 

Существует ли какое-либо обходное решение для этой проблемы без необходимости цитировать? Очевидно, я никогда не допущу эту ошибку, если @PeeHaa 埽 не даст пива снова, но я думаю, что любой ответ должен помочь образованным разработчикам PHP .

Примечание . – Это можно легко разрешить с помощью array_values , sort или любой функции php, которая изменяет положение ключа

пример

 sort($array); print_r($array); 

Вывод

 Array ( [0] => Duplicate key 1 [1] => Duplicate key 2 [2] => Duplicate key 3 [3] => 1 [4] => 2 [5] => 3 ) 

Вы можете использовать функцию array_values для сброса ключей массива.

Попробуй это:

 $obj = (object)array(1,2,3); $obj->{1} = "Duplicate key 1"; $obj->{2} = "Duplicate key 2"; $obj->{3} = "Duplicate key 3"; $array = (array)$obj ; $array = array_values($array); print_r($array); 

Производит следующее:

 Array ( [0] => 1 [1] => 2 [2] => 3 [3] => Duplicate key 1 [4] => Duplicate key 2 [5] => Duplicate key 3 ) 

Или вы можете даже использовать array_values ​​перед тем, как сделать это следующим образом:

 $array = array_values((array)$obj); 

Надеюсь это поможет!

Возможно, это не лучшее решение, но использование настраиваемой функции для создания массивов для объектов может решить часть проблемы.

 // function that convers an array to an object, and prefixes the numeric values with a string function toObj(Array $arr, $prefix = '_', $convertAll = false ) { foreach ($arr as $key => $value) { if (is_numeric($key) || $convertAll) { unset($arr[$key]); $arr[$prefix . $key] = $value; } } return (object)$arr; } $obj = toObj(array(1, 2, 3)); $obj->{'_0'} = "Duplicate key 0"; // either this way $obj->_1 = "Duplicate key 1"; // or this way $obj->{'_2'} = "Duplicate key 2"; $array = (array)$obj; print_r($array); с // function that convers an array to an object, and prefixes the numeric values with a string function toObj(Array $arr, $prefix = '_', $convertAll = false ) { foreach ($arr as $key => $value) { if (is_numeric($key) || $convertAll) { unset($arr[$key]); $arr[$prefix . $key] = $value; } } return (object)$arr; } $obj = toObj(array(1, 2, 3)); $obj->{'_0'} = "Duplicate key 0"; // either this way $obj->_1 = "Duplicate key 1"; // or this way $obj->{'_2'} = "Duplicate key 2"; $array = (array)$obj; print_r($array); 

Результат:

 Array ( [_0] => Duplicate key 0 [_1] => Duplicate key 1 [_2] => Duplicate key 2 ) 

Хотя это похоже на решение array_values , оно имеет преимущество по-прежнему держать ключи, по крайней мере, в определенной степени.

То, как я это вижу, единственное решение (т. Е. Единственное, что не является уродливым взломом) – это прекратить использование анонимных объектов и определить класс для этой цели. Это не должно быть сложным:

 class SimpleArrayObject { public function __construct($array = null) { foreach ((array) $array as $key => $value) { $this->{$key} = $value; // implicitly calls __set() } } public function __set($key, $value) { $this->{(string) $key} = $value; } } 

Из-за использования __set() и определения всего как динамических общедоступных свойств, это все равно будет хорошо работать с json_encode() , foreach , casting и всеми другими вещами, которые вы ожидаете от stdClass . Однако это принудительно вводит тип строки для имен свойств, что означает, что перекрывающиеся свободные типы больше не возможны.

Вы также можете определить вспомогательную функцию, которая позволит вам сделать синтаксис «casting» совершенно понятным, что происходит:

 function object($value) { if (is_object($value)) { return $value; } if (!is_array($value)) { // mimic the behaviour of a regular cast $value = array('scalar' => $value); } return new SimpleArrayObject($value); } 

Посмотрите, что произойдет:

 $obj = object(array(1,2,3)); $obj->{1} = "Duplicate key 1"; $obj->{2} = "Duplicate key 2"; $obj->{3} = "Duplicate key 3"; $array = (array)$obj ; print_r($array); 

Выход :

 Array ( [0] => 1 [1] => Duplicate key 1 [2] => Duplicate key 2 [3] => Duplicate key 3 )