Aller au contenu

Comparer 2 chaines de caractères


Compte supprimé

Sujets conseillés

Salut le hub !

J'ai mis en place sur mon site un semblant de wiki qui permet aux internautes de faire des modification au contenu. Pour la validation, je voudrais afficher la version actuelle avec le texte rajouté en rouge (par exemple) texte supprimé barré.

exemple : le petit chat félin gris

Vous avez des idées ?

Modifié par jeroen
Lien vers le commentaire
Partager sur d’autres sites

Comparer les caractères un à un, dés que ça commence à changer, ajouter les caractères de ton ancienne chaîne en barré puis mettre le text en rouge jusque ça devienne de nouveau le même.

J'espère que tu m'as compris, aussinon, je réexplique. ;)

Lien vers le commentaire
Partager sur d’autres sites

Ahaha, très bonne question.

Je pars jusque dimanche, j'essaierai de me pencher sur la question quand je reviens (j'aime bien les défis).

Une idée: Comparer une dizaine de caractères, si c'est les mêmes... C'est caisse. Mais comment??

Lien vers le commentaire
Partager sur d’autres sites

Tu prends ton texte, tu le découpes en morceaux, au niveau des espaces. Puis tu prends chaque mot, et tu le compares.

Le problème étant de trouver l'endroit où ce mot se trouvait..

En fait, quand tu regardes un peu comment bosse Word, tu t'apercoit qu'il note (en caractères cachés) tous les mots modifiés, il met tous ces mots en les mots cachés, au fur et à mesure qu'ils sont modifiés par l'utlisateur. Après, il lui suffit de montrer les mots cachés.

Le problème, c'est que pour faire ca avec Php, il faudrait plus d'interaction avec le serveur. :(

La solution pourrait consister à cacher des balises, avant que ca ne soit modifié. Au lieu du texte :

"le petit chaperon rouge",

tu aurais :

"[0]le [1]petit [2]chaperon [3]rouge[4]",

L'idée étant que lorsque l'utilisateur modifie un mot, par exemple "rouge" :

"[0]le [1]petit [2]chaperon [3]bleu[4]",

Tu t'apercoives que le mot contenu entre les balises [3] et [4] soit changé.

Un indice, tu peux te servir des caractères spéciaux, qui sont cachés et donc inaccessibles à l'utilisateur, pour parsemer ton texte de 'balises'.

Anonymus.

Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

je te propose ça :

<?php
$str1 = "Once there was a boy named Bart and a girl named Lisa.";
$str2 = "Once upon a time there was a girl named Lisa.";

echo "Old String: " . $str1 . "<br>";
echo "New String: " . $str2 . "<br>";
echo "Difference: " . diff_to_html($str1, $str2);

function diff_rek(&$a1,&$a2,$D,$k,&$vbck) {
$x=$vbck[$D][$k]; $y=$x-$k;
if ($D==0) {
if ($x==0) {
return array(array(),array());
} else {
return array(array_slice($a1,0,$x),array_fill(0,$x,"b"));
}
}
$x2=$vbck[$D-1][$k+1];
$y2=$vbck[$D-1][$k-1]-($k-1);
$xdif=$x-$x2; $ydif=$y-$y2;
$l=min($x-$x2,$y-$y2);
$x=$x-$l;
$y=$y-$l;
if ($x==$x2) {
$res=diff_rek($a1,$a2,$D-1,$k+1,$vbck);
array_push($res[0],$a2[$y-1]);
array_push($res[1],"2");
if ($l>0) {
$res[0]=array_merge($res[0],array_slice($a2,$y,$l));
$res[1]=array_merge($res[1],array_fill(0,$l,"b"));
}
} else {
$res=diff_rek($a1,$a2,$D-1,$k-1,$vbck);
array_push($res[0],$a1[$x-1]);
array_push($res[1],"1");
if ($l>0) {
$res[0]=array_merge($res[0],array_slice($a1,$x,$l));
$res[1]=array_merge($res[1],array_fill(0,$l,"b"));
}
}
return $res;
}

function arr_diff(&$a1,&$a2) {
$max=70;
$c1=count($a1);
$c2=count($a2);
$v[1]=0;
for ($D=0; $D<=$max; $D++) {
for ($k=-$D; $k<=$D; $k=$k+2) {
if (($k==-$D) || ($k!=$D && $v[$k-1]<$v[$k+1])) {
$x=$v[$k+1];
} else {
$x=$v[$k-1]+1;
}
$y=$x-$k;
while (($x<$c1)&&($y<$c2)&&($a1[$x]==$a2[$y])) {
$x++;
$y++;
}
$v[$k]=$x;
if (($x>=$c1)&&($y>=$c2)) {
$vbck[$D]=$v;
return diff_rek($a1,$a2,$D,$c1-$c2,$vbck);
};
}
$vbck[$D]=$v;
};
return -1;
}

// Returns a nicely formatted html string
function diff_to_html($oldString, $newString)
{
$a1 = explode(" ", $oldString);
$a2 = explode(" ", $newString);
$result = arr_diff($a1, $a2);

foreach ($result[0] as $num => $foo) {
$source = $result[1][$num];
$element = $result[0][$num];

switch ($source) {
case "1":
$pre = "<font color=red><s>";
$post = "</s></font>";
break;
case "2":
$pre = "<font color=green>";
$post = "</font>";
break;
case "b":
$pre = "";
$post = "";
break;
}
// VERTICAL OUTPUT:
// $return .= $num . $pre . " " . $source .
// " " . $element . $post . "<br>";
// READABLE OUTPUT:
$return .= $pre . $element . $post . " ";
}
return $return;
}
?>

Ce n'est pas de moi...mais j'ai pris la peine de te l'indenter proporement...simplement on le voit pas trop (hein Dan ;). C'est un mélange de source trouvées ici: http://www.php.net/array_diff

Le texte enlevé est en rouge/barré...et le texte ajouté est en vert...et le texte modifié est rouge/barré et à côté le texte modifié est en vert, mais tu peux changer cela dans la source.

Modifié par TheRec
Lien vers le commentaire
Partager sur d’autres sites

Il est géant, ce script !

Y'a juste une petite erreur, c'est étrange, d'ailleurs :

Quand on tape le second texte, mais que l'on ajoute un point supplémentaire, ou que l'on met un espace, tout à la fin, il considère le dernier mot comme différent.

Essaies, avec la même ponctuation à la fin de la phrase, puis tu changes de ponctuation. Ca change le mot.

Sinon, vraiment bien ;)

Lien vers le commentaire
Partager sur d’autres sites

Ouais...erreur je ne sais pas, peut être que je t'ai mal compris, techniquement c'est bien un changement dans la phrase. Les mots sont pris "un à un" et que les espaces comptent, tout comme la ponctuation à l'interieur des mots qui les précède (Apparemment. Je ne me suis pas penché sur tout l'aglorithme).

Cela dit ça pose un problème tout autre, une balise comme <br/> qui serait écrite comme <br /> est "cassé" pour noter la différence entre les deux...alors que sémentiquement les deux sont semblables et correctes...donc si ton texte contient de l'HTML il y aura peut-être des problèmes.

Mais bon il faut tout de même garder une mesure, si on commence a inclure des expcetions dans la comparaison cela va généerer un usine à "case" (pardon pour le mauvais jeu de mots) pour une fonction qui n'est pas essentiellement faite pour des différences scabreuses...

Lien vers le commentaire
Partager sur d’autres sites

Un peu le même problème que le "mien" ... fait un teste en ajoutant un espace avant un point ...

Texte original :

Bonjour.

Texte modifié :

Bonjour .

Résultat :

<span class="corrige">Bonjour.</span> <span class="correction">Bonjour</span>

La correction serait plus juste si elle était placée avant le point et on voit pas vraiment oû se situe la différence... je fais presque la même remarque à mon bot de code sauf qu'on "voit" pourquoi il y a correction en gros...

**EDIT** Je vois que je suis pas le seul à ne pas trouver le someil hein ;) Allez bonne nuit !

Modifié par TheRec
Lien vers le commentaire
Partager sur d’autres sites

Du bon boulot mais il l'ai vu encore un autre bug (en plus des problèmes en fin de ligne) :

si je corrige "la petite souris blanche" en "le petit rat blanc" il corrige mot à mot, alors que c'est nettement plus lisible si la correction se fait "en bloc"

Je crois que je vais aussi tenter quelque chose....

ps : est ce que tu peux faire une sortie directement mise en forme sur ta page, ce sera plus rapide pour les tests ^_^

Cordialement, et Merci :D

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

mais en fait maintenant il a le même comportement que "mon" script pour la ponctuation de fin de chaîne... ou alors j'ai mal compris l'erreur que vous me signaliez avant :S

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

mais en fait maintenant il a le même comportement que "mon" script pour la ponctuation de fin de chaîne... ou alors j'ai mal compris l'erreur que vous me signaliez avant :S

<{POST_SNAPBACK}>

c'est ça. En fait il ne faudrait séparer la ponctuation simple (.,) du texte ...

Bref c'est un beau challenge :P

Lien vers le commentaire
Partager sur d’autres sites

Bon, le problème des fins de ligne (si on peut appeler ça comme ça) est corrigé. Je vais essayer autre pour correction e n bloc, mais je promets rien :S

<{POST_SNAPBACK}>

Dans ce cas, le problème des fins de lignes n'est pas résolu dans le script d'e.MiLoU ...enfin il me semble, vu que le comportement est le même qu'avec le "mien"... Mais comme je l'ai dit techniquement il y a une différence entre les chaînes, les espaces doivent être considérés et il ne peuvent qu'être "liés" avec un mot ou une poncutation sinon il faudrait considérer les espaces entre les mots différemment (des espaces significatifs et d'autres non-significatifs...une hérésie car dans certains cas ils peuvent être significatifs dans certains textes et dans d'autres non...et cela me semble difficile car il faudrait comparer avec ce qui se trouve avant et après le caractère en cours...et pour le script que j'ai porposé ce n'est pas possible vu qu'il y a comparaison mot à mot dans la mesure où on cherche les différences entre deux tableaux (si on schématise le fonctionnement)...

Lien vers le commentaire
Partager sur d’autres sites

Oui, j'allais le dire :D

Bon, en tout cas, dans mon script, il reste plus que le bug des ponctuations (on va appeler ça comme ça) et des grande zone de texte à barré.

J'y réfléchis, j'ai déjà une idée mais là je dois y aller.

Url est ici

PS: Tester pas trop trop quand même car c'est un serveur mutualisé.

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...