Неожиданные результаты с array_uintersect_assoc(), когда обратный вызов возвращает нечисловую строку
Я звоню с функцией обратного вызова
strpbrk()
чтобы продемонстрировать, как различные возвращаемые значения оцениваются в зависимости от типа.
Учитывая ассоциативный массив стогов сена, например:
[
'one' => '0',
'two' => '1',
'three' => '0',
'four' => '1',
'five' => 'a',
'six' => 'b',
'seven' => 'a',
'eight' => 'b'
]
И ассоциативный ряд иголок вроде:
[
'one' => '1',
'two' => '0',
'three' => '0',
'four' => '1',
'five' => 'a',
'six' => 'b',
'seven' => 'a'
'eight' => 'b',
]
Код:
var_export(array_uintersect_assoc($array1, $array2, 'strpbrk'));
Вывод:
['four' => '1']
Поскольку возвращаемые строковые значения
a
и
b
правдивы, почему не элементы с ключами
seven
и
eight
включены в результаты?
Связанный
array_uintersect_assoc()
страницы, которые конкретно не затрагивают эту проблему:
1 ответ
В указано, что возвращаемое значение будет оцениваться как
int
значение типа не значение логического типа.
callback(mixed $a, mixed $b): int
Эта нативная функция предназначена для ожидания возвращаемого значения при трехстороннем сравнении. Это означает, что элементы, возвращающие нулевые значения, сохраняются, а все остальное удаляется.
При сравнении значений с ключом (
strpbrk('a', 'a')
) возвращаемое значение является строковым значением. (Следующее объяснение применимо для сравнения значений с ключом.) Хотя правильно то, что считается «истинным», потому что, когда оно приводится как логическое значение, оно становится . Также правильно, что логическое значение при приведении к значению int станет
1
. Однако, когда
a
напрямую приводится как значение int, оно становится
0
-- вот как
array_unintersect_assoc()
оценивает возвращаемое значение обратного вызова, и это объясняет, почему элементы
seven
а также
eight
не сохраняются в массиве результатов. (руководстве по PHPПолная демонстрация этой задачи и приведенный ниже фрагмент )
var_export([
// haystack, then needle
'0:1' => strpbrk('0', '1'), // false
'1:0' => strpbrk('1', '0'), // false
'0:0' => strpbrk('0', '0'), // '0'
'1:1' => strpbrk('1', '1'), // '1'
'a:b' => strpbrk('a', 'b'), // false
'b:a' => strpbrk('b', 'a'), // false
'a:a' => strpbrk('a', 'a'), // 'a'
'b:b' => strpbrk('b', 'b'), // 'b'
'a as bool' => (bool)'a', // true
'a as int' => (int)'a', // 0
'a as bool then int' => (int)(bool)'a', // 1
]);
Поскольку так много фрагментов, демонстрирующих
array_uintersect_assoc()
(включая руководство) все использовать
strcasecmp()
в качестве обратного вызова я предложу несколько других обратных вызовов, чтобы предоставить исследователям больше контекста.
В конечном счете, недостаточно понимать , как разные типы переменных жонглируются логическими значениями . Крайне важно, чтобы разработчики понимали, как различные типы значений преобразуются в целые числа .
Немного неудобно/противоречиво сохранять значения, которые возвращают нулевое целое число, потому что ноль является ложным значением. Для тех, кто использует
str_contains()
,
str_starts_with()
,
str_ends_with()
и т. д., которые возвращают логический результат, вам нужно будет инвертировать нативную функцию из
uintersect
к
udiff
таким образом
true
логическое возвращаемое значение обрабатывается правильно.
стркмп()
Код: (демонстрация разбивки )
var_export(
array_uintersect_assoc([
['one' => 'a', 'two' => 'aa', 'three' => 'a', 'four' => 'aa'], // string1s
['one' => 'aa', 'two' => 'a', 'three' => 'a', 'four' => 'aa'], // string2s
'strcmp'
])
);
// ['three' => 'a', 'four' => 'aa']
подрезать()
Код: (демонстрация разбивки )
var_export(
array_uintersect_assoc([
['one' => 'a', 'two' => 'ab', 'three' => '0', 'four' => '1'], // strings
['one' => 'ab', 'two' => 'a', 'three' => '1', 'four' => '0'], // masks
'trim'
])
);
// ['one' => 'a', 'two' => 'ab', 'three' => '0']
strcspn()
Код: (демонстрация разбивки )
var_export(
array_uintersect_assoc([
['one' => 'a', 'two' => 'ba', 'three' => 'a', 'four' => 'ba'], // strings
['one' => 'ba', 'two' => 'a', 'three' => 'a', 'four' => 'ba'], // masks
'strcspn'
])
);
// ['one' => 'a', 'three' => 'a', 'four' => 'ba']
str_repeat()
Код: (демонстрация разбивки )
var_export(
array_uintersect_assoc([
['one' => 0, 'two' => 1, 'three' => 0, 'four' => 1], // strings
['one' => 1, 'two' => 0, 'three' => 0, 'four' => 1], // times
'str_repeat'
])
);
// ['one' => 0, 'two' => 1, 'three' => 0]
str_contains()
Код: (демонстрация разбивки )
var_export(
array_uintersect_assoc([
['one' => 'a', 'two' => 'aa', 'three' => 'a', 'four' => 'aa'], // haystacks
['one' => 'aa', 'two' => 'a', 'three' => 'a', 'four' => 'aa'], // needles
'str_contains'
])
);
// ['one' => 'a']