数组中的重复键

时间:2013-04-09 11:09:34

标签: php arrays

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

示例:

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

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

Output

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