2013-04-09 52 views
5

在類型轉換過程中防止重複鍵的最佳方法是什麼?Array中的重複鍵

例子:

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

是關於防止鍵或有關訪問正確的價值觀「複製」這個問題? – PeeHaa 2013-04-09 11:15:18

+0

@PeeHaa埽我會說這兩個.... – Baba 2013-04-09 11:17:59

回答

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

希望這有助於!

+0

'array_values'肯定的,但就像我說的'任何答案應該幫助教育的PHP developers' – Baba 2013-04-09 11:18:43

+0

你是什麼意思的「答案」應該幫助教育PHP開發人員?你的意思是這個問題的答案應該解釋的更好? – Matija 2013-04-09 11:21:33

+0

是'解釋better' .....了廣泛的開發。謝謝 – Baba 2013-04-09 11:23:04

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解決方案,它具有仍保持鍵,至少在一定程度上受益。

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

Output

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

+非常不錯...... – Baba 2013-04-09 11:39:30