5

在类型转换期间防止重复键的最佳方法是什么?

例子 :

//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
)

现在我知道有些聪明人会说它,因为一个keystring,另一个是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_valuessort或任何改变关键位置的 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
)
4

3 回答 3

1

在我看来,唯一的解决方案(即唯一不是丑陋的黑客)是停止使用匿名对象并为此目的定义一个类。它不需要复杂:

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
)
于 2013-04-09T11:37:25.220 回答
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);

希望这可以帮助!

于 2013-04-09T11:17:58.263 回答
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解决方案,但它的好处是仍然保留了密钥,至少在一定程度上是这样。

于 2013-04-09T11:36:32.723 回答