Я отвечал на этот вопрос сегодня, используя array_walk_recursive()
, и, учитывая array_walk_recursive()
образец выборки OP, мой ответ был на месте. Однако, когда OP использовал его на более крупном, реальном массиве, было обнаружено некоторое нежелательное поведение при условной проверке ключей с помощью ==
. В конце концов, использование ===
было достаточно, чтобы исправить проблему.
Вот минимальная демонстрация ( Demo Link ):
$array=[ 'key1'=>[ ['key1A'=>'v1'], ['key1B'=>'v2'], ['key1C'=>'v3'] ], 'key2'=>[ [0=>'v4'], [1=>'v5'], [2=>'v6'] ], 'key3'=>[ ["0"=>'v7'], ["1"=>'v8'], ["2"=>'v9'] ] ]; echo "Leafy nodes:\n-----\n"; array_walk_recursive($array,function($v,$k)use(&$result1){ echo "$k => $v\n"; if($k=='key1B'){ // buggy behavior with == if(!isset($result1[$v])){$result1[$v]=0;} ++$result1[$v]; } }); array_walk_recursive($array,function($v,$k)use(&$result2){ //echo "$k => $v\n"; if($k==='key1B'){ // no trouble with === if(!isset($result2[$v])){$result2[$v]=0;} ++$result2[$v]; } }); echo "\nIncorrect key-matching with ==\n"; var_export($result1); echo "\nCorrect key-matching with ===\n"; var_export($result2);
Вывод:
Leafy nodes: ----- key1A => v1 key1B => v2 key1C => v3 0 => v4 1 => v5 2 => v6 0 => v7 1 => v8 2 => v9 Incorrect key-matching with == array ( 'v2' => 1, 'v4' => 1, 'v7' => 1, ) Correct key-matching with === array ( 'v2' => 1, )
Поведение, похоже, состоит в том, что клавиши «нуль-иш» соответствуют key1B
. Если [0=>'v4']
закомментирован, то v5
не вставляется в $result1
; поэтому речь идет не о ключевой позиции в подмассиве, а о бремени на нулевом ключе.
Я хотел бы знать:
Наконец, если это не ошибка, я надеюсь, что мой пост поможет другим идентифицировать и избежать этого потенциального.
Это происходит потому, что преобразование типа php не выполняется, когда сравнение ===, но в == сравнение происходит после манипуляции типа.
для получения дополнительной информации ознакомьтесь с руководством ..
Операторы сравнения: http://www.php.net/manual/en/language.operators.comparison.php
PHP-тип указывает член в правой части оператора ==
на тип элемента с левой стороны. Так как $k
иногда равно целому числу, key1B
в целое число, равное 0.
Из руководства по PHP …
При использовании ==
(свободное сравнение) и одним из операндов является число, php выполняет манипуляцию типа в качестве предназначенной функции. Эффект в этом случае означает, что строка key1B
преобразуется в 0
когда $k
является числовой.
Это таблица свободных сравнений из таблицы таблиц сравнения типов PHP :
Это говорит о том, что при свободном сравнении строки и нуля результат будет TRUE
.
Вот еще одна демонстрация с использованием массива с циклом foreach:
Код:
$array=['v1','key1'=>'v2']; var_export($array); echo "\n"; foreach($array as $k=>$v){ echo "$k => $v"; echo ' ($k = ',gettype($k),")"; if($k=='key1'){ echo " loosely equal"; } echo "\n"; }
Вывод:
array ( 0 => 'v1', 'key1' => 'v2', ) 0 => v1 ($k = integer) loosely equal key1 => v2 ($k = string) loosely equal
* Заметьте, функция жонглирования типа запрещена, когда $k
присваивается тип: if((string)$k=='key1'){
Это сравнение не приведет к TRUE
когда $k
равно 0
.
Урок, который нужно убрать, заключается в том, что вы не на 100% уверены, что операнды, которые вы сравниваете, будут одного типа, лучше всего использовать строгое сравнение (
===
).