Если вы хотите описать функции PHP в одном предложении array_diff_uassoc
, Возможно, вы начнете с сравнения двух или более функций одновременно и возврата одних и тех же данных для значений ключей, которые отображаются в первой функции, но не в других функциях одновременно.
Недавно я увидел интересный вопрос о array_diff_uassoc
Только прочитав этот вопрос, мы сможем понять непонимание этой функции.
Вот упрощенная версия проблемы:
function comparekey($a,$b){ return 0; } $array1 = ['a'=>1,'b'=>2,'c'=>3,'d'=>4]; $array2 = ['a'=>2,'d'=>4,'e'=>6]; $res = array_diff_uassoc($array1,$array2,'comparekey'); var_dump($res);
Почему это оказалось так
['a'=>1,'c'=>3,'d'=>4];
Согласно обычной логике, array_diff_uassoc
Возвращает данные массива с другим ключом и другим значением. Если пользовательская функция сравнения возвращает 0, значение ключа остается тем же. Итак, что должна вернуть нормальная логика, так это
['a'=>1,'b'=>2,'c'=>3]
Ты действительно прав?
1. Является ли определяемая пользователем функция сравнением ключей двух массивов?
На самом деле, честно говоря, я так и думал в самом начале. Пока я не вывел a и B соответственно в пользовательской функции, я видел замечательный выходной контент и думал, что функция сравнения не так проста.
Чтобы упростить просмотр содержимого, используйте следующий массив вместо содержимого проблемы
function comparekey($a,$b){ echo $a.'-'.$b; return 0; } $array1 = ['a'=>1,'b'=>2,'c'=>3,'d'=>4]; $array2 = ['e'=>'2','f'=>5,'g'=>6]; $res = array_diff_uassoc($array1,$array2,'comparekey');
Вывод функции является
a-b b-c c-d e-f f-g a-e b-e c-e d-e
Таким образом, можно видеть, что определяемые пользователем функции передаются для сравнения Не всегда Является ключом из другого массива. Также возможно иметь один и тот же массив ключей.
2. Является ли пользовательская функция просто для сравнения того, равны ли значения ключей?
Конечно, нет. Сама функция сравнения-это сравнение размеров. Но дело не в том, равны ли значения ключа сравнения, которые мы понимаем. В соответствии с возвращаемым результатом, определяемым самостоятельно, положение внутреннего указателя PHP будет скорректировано, поэтому мы можем видеть, что следующее сравнение является A-E B-E C-E D-E
3. При сравнении значений ключей верно ли сравнивать значения ключей элементов массива с одинаковым именем ключа?
Этот тоже не такой. На самом деле это происходит потому, что результат массива функции сравнения влияет на изменение положения указателя массива в PHP. Различные способы изменения приведут к окончательному сравнению цен, которое, как мы думаем, не является сравнением стоимости одного и того же ключевого имени.
Взгляните на PHP исходный код , array_diff_uassoc, наконец, передается через php
_array_diff
Функцию.
static void php_array_diff(void *base, size_t nmemb, size_t siz, compare_func_t cmp, swap_func_t swp) { ... if (hash->nNumOfElements > 1) { if (behavior == DIFF_NORMAL) { zend_sort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket), diff_data_compare_func, (swap_func_t)zend_hash_bucket_swap); } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */ zend_sort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket), diff_key_compare_func, (swap_func_t)zend_hash_bucket_swap); } } ... }
Можно увидеть diff_key_compare_func
Передано в функцию сортировки. Таким образом, возвращаемый результат пользовательской функции повлияет на временную переменную списки
Вывод.
В PHP сначала сортируются все входные массивы. Таким образом, в пользовательской функции мы видим, что предыдущее содержимое вывода предназначено для сравнения имен ключей массива по очереди.
Истинное лицо
Когда имена ключей входного массива находятся в хорошем порядке, первый массив следует сравнить с именами ключей других массивов.
1) Сравните имена ключей текущих элементов первого массива с именами сравниваемых элементов до тех пор, пока первый не будет таким же или сравнение не закончится.
RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0]))); while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) { for (i = 1; i < arr_argc; i++) { Bucket *ptr = ptrs[i]; if (behavior == DIFF_NORMAL) { while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = diff_data_compare_func(ptrs[0], ptrs[i])))) { ptrs[i]++; } } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */ while (Z_TYPE(ptr->val) != IS_UNDEF && (0 != (c = diff_key_compare_func(ptrs[0], ptr)))) { ptr++; } } ... } ... }
2) Если имена ключей совпадают (функция сравнения имен ключей возвращает 0), то равны ли значения ключей сравнения. Если нет, для C установлено значение – 1, чтобы продолжить сравнение элементов следующего массива.
RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0]))); while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) { ... for (i = 1; i < arr_argc; i++) { ... if (!c) { ... if (diff_data_compare_func(ptrs[0], ptr) != 0) { c = -1; if (key_compare_type == DIFF_COMP_KEY_USER) { BG(user_compare_fci) = *fci_key; BG(user_compare_fci_cache) = *fci_key_cache; } } ... } ... } ... }
3) Согласно результатам сравнения, если результаты сравнения не равны, то сравните все элементы другого массива со следующим элементом первого массива.
Если результаты сравнения равны), удалите имя ключа, соответствующее возвращенному массиву (скопированному из первого массива).
RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0]))); while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) { ... if (!c) { for (;;) { p = ptrs[0]; p = ptrs[0]; if (p->key == NULL) { zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); } else { zend_hash_del(Z_ARRVAL_P(return_value), p->key); } if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) { goto out; } ... } } else { for (;;) { if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) { goto out; } ... } ... } ... }
Следующие массивы и пользовательские функции являются примерами, иллюстрирующими процесс сравнения.
function comparekey($a,$b){ return 0; } $array1 = ['a'=>1,'b'=>2,'c'=>3,'d'=>4]; $array2 = ['a'=>2,'d'=>4,'e'=>6];
Установите возвращаемый массив, а не массив 1
Сравните имена ключей “a” и “a”, если они равны, затем сравните array1 [‘a ‘]! = $array2 [‘a’].
Сравните имена ключей “B”, “a”, если они равны, затем сравните array1 [‘b ‘] = = $массив 2 [‘a’], удалите значение ключа “B” возвращаемого массива
Сравните имена ключей “C”, “a”, если они равны, затем сравните array1 [‘c ‘]! = $array2 [‘a’].
Сравните имена ключей “d”, “a”, если они равны, затем сравните array1 [‘c ‘]! = $array2 [‘a’].
Таким образом, конечный возвращаемый массив является
$res = ['a'=>1,'c'=>3,'d'=>4]
резюме
Таким образом, пользовательские функции не делают нас полностью пользовательскими. Пользовательская функция возвращает другой результат. Существует множество массивов PHP, которые предоставляют пользовательские методы функций. Однако, если возвращаемое значение вашей пользовательской функции “искажено”, например, функция в этой задаче всегда одинакова, но ключевое значение одного и того же массива в PHP не может быть одинаковым, поэтому результат сравнения этой пользовательской функции “проблематичен”. В соответствии с этой предпосылкой результаты, возвращаемые PHP, также могут иметь неожиданный результат.
Когда вы используете его в следующий раз array_diff_uassoc
При использовании функции, вы должны знать, что эта пользовательская функция предназначена не только для сравнения того, совпадают ли имена ключей двух массивов, но и для того, чтобы повлиять на внутреннюю сортировку входных массивов PHP перед сравнением; возвращаемый результат пользовательской функции напрямую повлияет на порядок изменения указателей массива PHP, что приведет к различным результатам сравнения;
Статья впервые появилась в открытом доступе PS: ею нелегко поделиться. Если вы считаете, что это полезно, не забудьте поделиться