Vous pouvez utiliser une belle propriété de XOR au niveau du bit (^
) pour atteindre ce: en principe, lorsque vous xor de deux cordes en même temps, les caractères sont les mêmes deviendront des octets nuls ("\0"
). Donc, si nous xor, les deux chaînes, nous avons juste besoin de trouver la position du premier non-octet null à l'aide de strspn
:
$position = strspn($string1 ^ $string2, "\0");
C'est tout là est à lui. Alors, regardons un exemple:
$string1 = 'foobarbaz';
$string2 = 'foobarbiz';
$pos = strspn($string1 ^ $string2, "\0");
printf(
'First difference at position %d: "%s" vs "%s"',
$pos, $string1[$pos], $string2[$pos]
);
Qui sera de sortie:
Première différence à la position 7: "un" vs "je"
Donc ça devrait le faire. C'est très efficace car elle n'utilise que les fonctions C, et ne nécessite qu'une seule copie de la mémoire de la chaîne.
Edit: Une Solution Multi-Octets Dans Le Même Sens:
function getCharacterOffsetOfDifference($str1, $str2, $encoding = 'UTF-8') {
return mb_strlen(
mb_strcut(
$str1,
0, strspn($str1 ^ $str2, "\0"),
$encoding
),
$encoding
);
}
D'abord la différence au niveau de l'octet est trouvé en utilisant la méthode ci-dessus, et le décalage est mappé au niveau du caractère. Ceci est fait en utilisant l' mb_strcut
de la fonction, qui est fondamentalement substr
mais en honorant les jeux de caractères multioctets limites.
var_dump(getCharacterOffsetOfDifference('foo', 'foa')); // 2
var_dump(getCharacterOffsetOfDifference('©oo', 'foa')); // 0
var_dump(getCharacterOffsetOfDifference('f©o', 'fªa')); // 1
Ce n'est pas aussi élégante que la première solution, mais il est encore un one-liner (et si vous utilisez le codage par défaut un peu plus simple):
return mb_strlen(mb_strcut($str1, 0, strspn($str1 ^ $str2, "\0")));