Вы можете использовать красивое свойство побитовое XOR (^
) для достижения этого: в основном, когда вы xor две строки вместе, одинаковые символы станут нулевыми байтами ("\0"
). Поэтому, если мы xor двух строк, нам просто нужно найти позицию первого ненулевого байта, используя strspn
:
$position = strspn($string1 ^ $string2, "\0");
Это все, что нужно сделать. Итак, давайте посмотрим на пример:
$string1 = 'foobarbaz';
$string2 = 'foobarbiz';
$pos = strspn($string1 ^ $string2, "\0");
printf(
'First difference at position %d: "%s" vs "%s"',
$pos, $string1[$pos], $string2[$pos]
);
Будет выведено:
Первое различие в позиции 7: "a" против "i"
Так что это должно сделать это. Это очень эффективно, так как он использует только функции C и требует только одну копию памяти строки.
Редактировать: решение MultiByte по тем же линиям:
function getCharacterOffsetOfDifference($str1, $str2, $encoding = 'UTF-8') {
return mb_strlen(
mb_strcut(
$str1,
0, strspn($str1 ^ $str2, "\0"),
$encoding
),
$encoding
);
}
Сначала с помощью вышеуказанного метода определяется разница на уровне байтов, а затем смещение отображается на уровне символов. Это делается с помощью функции mb_strcut
, которая в основном substr
, но учитывает границы многобайтовых символов.
var_dump(getCharacterOffsetOfDifference('foo', 'foa')); // 2
var_dump(getCharacterOffsetOfDifference('©oo', 'foa')); // 0
var_dump(getCharacterOffsetOfDifference('f©o', 'fªa')); // 1
Это не так элегантно, как первое решение, но это все же однострочный (и если вы используете кодировку по умолчанию немного проще):
return mb_strlen(mb_strcut($str1, 0, strspn($str1 ^ $str2, "\0")));