Неожиданные результаты с 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']
Другие вопросы по тегам