在类型转换期间防止重复键的最佳方法是什么?
示例:
//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
)
答案 0 :(得分:1)
您可以使用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);
希望这有帮助!
答案 1 :(得分:1)
也许不是最好的解决方案,但使用自定义函数将数组转换为对象可以解决部分问题。
// 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
解决方案类似,但它仍然保留了密钥的好处,至少在一定程度上。
答案 2 :(得分:1)
我看到这个的方式, only 解决方案(即唯一不是丑陋的黑客)是停止使用匿名对象并为此目的定义一个类。它不需要复杂:
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
,强制转换以及您期望的所有其他内容,这仍然会很好用stdClass
。但是,这会强制使用属性名称的字符串类型,这意味着不再可能出现重叠的松散类型。
您还可以定义一个辅助函数,以便让“铸造”语法非常清楚发生了什么:
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
)